日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

pycharm中配置r语言_【R语言】R语言中的循环

發(fā)布時(shí)間:2025/3/15 68 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pycharm中配置r语言_【R语言】R语言中的循环 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

編程中減少代碼重復(fù)的兩個(gè)工具,一是循環(huán),一是函數(shù)。

循環(huán),用來(lái)處理對(duì)多個(gè)同類輸入做相同事情(即迭代),如對(duì)不同列做相同操作、對(duì)不同數(shù)據(jù)集做相同操作。

R語(yǔ)言有三種方式實(shí)現(xiàn)循環(huán):

(1)for循環(huán)、while循環(huán)

(2)apply函數(shù)族

(3)泛型函數(shù)map

一. for循環(huán)、while循環(huán)

首先作兩點(diǎn)說(shuō)明:

(1)關(guān)于“for循環(huán)運(yùn)行速度慢”的說(shuō)法,實(shí)際上已經(jīng)過(guò)時(shí)了,現(xiàn)在的R、Matlab等軟件經(jīng)過(guò)多年的內(nèi)部?jī)?yōu)化已經(jīng)不慢了,之所以表現(xiàn)出來(lái)慢,是因?yàn)槟銢]有注意兩個(gè)關(guān)鍵點(diǎn):

  • 提前為保存循環(huán)結(jié)果分配存儲(chǔ)空間;
  • 為循環(huán)體中涉及到的數(shù)據(jù)選擇合適的數(shù)據(jù)結(jié)構(gòu)。

(2)apply函數(shù)族和泛型函數(shù)map能夠更加高效簡(jiǎn)潔地實(shí)現(xiàn)一般的for循環(huán)、while循環(huán),但這不代表for循環(huán)、while循環(huán)就沒用了,它們可以在更高的層次使用(相對(duì)于在逐元素級(jí)別使用)

1. 基本for循環(huán)

例如,有如下的tibble數(shù)據(jù):

library(tidyverse)df <- tibble(a = rnorm(10),b = rnorm(10),c = rnorm(10),d = rnorm(10) )

用復(fù)制-粘貼法,計(jì)算每一列的中位數(shù):

median(df$a) median(df$b) median(df$c) median(df$d)

為了避免“粘貼-復(fù)制多于兩次”,改用for循環(huán)實(shí)現(xiàn):

output <- vector("double", ncol(df)) #1.輸出 for (i in seq_along(df)) { #2.迭代器output[[i]] <- median(df[[i]]) #3.循環(huán)體 } output #輸出結(jié)果略

for循環(huán)有三個(gè)組件:

(1) 輸出:output <- vector("double", length(x))

在循環(huán)開始之前,最好為輸出分配足夠的存儲(chǔ)空間,這樣效率更高:若每循環(huán)一次,就用c()合并一次,效率會(huì)很低下。

通常是用vector()函數(shù)創(chuàng)建一個(gè)給定長(zhǎng)度的空向量,它有兩個(gè)參數(shù):向量類型(logical, integer, double, character等)、向量長(zhǎng)度。

(2)迭代器:i in seq_along(df)

確定怎么循環(huán):每次for循環(huán)將對(duì)i賦一個(gè)seq_along(df)中的值,可將i理解為代詞it. 其中seq_along()是“1:length(df)”的安全版本,它能保證遇到長(zhǎng)度為0的向量時(shí),仍能正確工作:

y <- vector("double", 0) seq_along(y)

1:length(y)

你可能不會(huì)故意創(chuàng)建長(zhǎng)度為0的向量,但容易不小心創(chuàng)建,則會(huì)導(dǎo)致報(bào)錯(cuò)。

(3) 循環(huán)體:output[[i]] <- median(df[[i]])

即執(zhí)行具體操作的代碼,它將重復(fù)執(zhí)行,每次對(duì)不同的i值。

第1次迭代將執(zhí)行:output[[1]] <- median(df[[1]]),

第2次迭代將執(zhí)行:output[[2]] <- median(df[[2]]),

……

2. for循環(huán)變種

基本的for循環(huán)有4個(gè)變種:

(1) 修改已存在的對(duì)象,創(chuàng)建的新對(duì)象

有時(shí)需要用for循環(huán)修改一個(gè)已存在的對(duì)象,例如,對(duì)數(shù)據(jù)框 df 的每一列做歸一化:

rescale01 <- function(x) {rng <- range(x, na.rm = TRUE)(x - rng[1]) / (rng[2] - rng[1]) } df$a <- rescale01(df$a) df$b <- rescale01(df$b) df$c <- rescale01(df$c) df$d <- rescale01(df$d)

用for循環(huán)來(lái)做,先考慮其3個(gè)組件:

輸出:已經(jīng)存在,與輸入相同。

迭代器:可以將數(shù)據(jù)框看作是多個(gè)列構(gòu)成的列表,故可以用seq_along(df)來(lái)迭代每一列。

循環(huán)體:應(yīng)用函數(shù)rescale01().

于是寫出如下的for循環(huán):

for (i in seq_along(df)) {df[[i]] <- rescale01(df[[i]]) }

通常來(lái)說(shuō),你可以用這種循環(huán)來(lái)修改一個(gè)列表或數(shù)據(jù)框,注意這里是用[[ ]], 而不是[ ]. 因?yàn)樵酉蛄孔詈糜肹[ ]], 這樣能清楚地表明你處理的是一個(gè)單獨(dú)的元(而不是子集)。

(2) 循環(huán)模式

· 根據(jù)數(shù)值索引:for(i in seq_along(xs), 用x[[i]] 提取值。

· 根據(jù)元素值:for(x in xs). 若你只關(guān)心附帶作用,這特別有用。例如繪圖、保存文件等,因?yàn)楹茈y高效率地保存這種結(jié)果。

· 根據(jù)名字:for(nm in names(xs)). 對(duì)每個(gè)名字,訪問(wèn)其對(duì)應(yīng)的值 x[[nm]], 若你需要使用圖形標(biāo)題或文件的名稱,這就很有用。當(dāng)創(chuàng)建命名的輸出時(shí),確保按如下方式命名結(jié)果向量:

results <- vector("list", length(x)) names(results) <- names(x)

注:用數(shù)值索引迭代是最常用的形式,因?yàn)橹灰o定位置,名字和元素值都可以提取:

for (i in seq_along(x)) {name <- names(x)[[i]]value <- x[[i]] }

(3) 結(jié)果長(zhǎng)度未知

有時(shí)候,你可能不知道輸出結(jié)果有多長(zhǎng)。例如,你想要模擬一些長(zhǎng)度隨機(jī)的隨機(jī)向量。你可能優(yōu)先想到通過(guò)逐步增加長(zhǎng)度的方法解決該問(wèn)題:

means <- c(0, 1, 2) output <- double() for (i in seq_along(means)) {n <- sample(100, 1)output <- c(output, rnorm(n, means[[i]])) } str(output)

但這種做法很低效,因?yàn)槊看蔚?#xff0c;R都要復(fù)制上一次迭代的全部數(shù)據(jù),其復(fù)雜度為

.

一個(gè)好的方法是,先將結(jié)果保存為列表,等循環(huán)結(jié)束再將列表重組為一個(gè)單獨(dú)的向量:

out <- vector("list", length(means)) for (i in seq_along(means)) {n <- sample(100, 1)out[[i]] <- rnorm(n, means[[i]]) } str(out)

str(unlist(out))

這里是用unlist()函數(shù)將一個(gè)向量的列表攤平為一個(gè)單獨(dú)的向量。更嚴(yán)格的方法是用purrr包中的flatten_dbl(), 若輸入不是double型的列表,將會(huì)報(bào)錯(cuò)。

還有兩種結(jié)果長(zhǎng)度未知的情形:

· 生成一個(gè)長(zhǎng)字符串。不是用paste()函數(shù)將上一次的迭代結(jié)果拼接到一起,而是將結(jié)果保存為字符向量,再用函數(shù)paste(output, collapse= " ")合并為一個(gè)單獨(dú)的字符串;

· 生成一個(gè)大的數(shù)據(jù)框。不是依次用rbind()函數(shù)合并每次迭代的結(jié)果,而是將結(jié)果保存為列表,再用dplyr包中的bind_rows(output)函數(shù)合并成一個(gè)單獨(dú)的數(shù)據(jù)框。

所以,遇到上述模式時(shí),要先轉(zhuǎn)化為更復(fù)雜的結(jié)果對(duì)象,最后再做一步合并。

(4) 迭代次數(shù)未知(while循環(huán))

有時(shí)候你甚至不知道輸入序列有多長(zhǎng),這通常出現(xiàn)在做模擬的時(shí)候。例如,你可能想要在一行中循環(huán)直到連續(xù)出現(xiàn)3個(gè)“Head”,此時(shí)不適合用for循環(huán),而是適合用while循環(huán)。

while循環(huán)更簡(jiǎn)單些,因?yàn)樗话瑑蓚€(gè)組件:條件、循環(huán)體:

while (condition) {#body }

While循環(huán)是比f(wàn)or循環(huán)更一般的循環(huán),因?yàn)閒or循環(huán)總可以改寫為while循環(huán),但while循環(huán)不一定能改寫為for循環(huán):

for (i in seq_along(x)) {#循環(huán)體 } #等價(jià)于 i <- 1 while (i <= length(x)) {#循環(huán)體i <- i + 1 }

下面用while循環(huán)實(shí)現(xiàn):拋一枚硬幣直到連續(xù)出現(xiàn)3次“正面”,需要的次數(shù):

flip <- function() sample(c("Tail", "Head"), 1)flips <- 0 nheads <- 0while (nheads < 3) {if (flip() == "Head") {nheads <- nheads + 1} else {nheads <- 0}flips <- flips + 1 } flips

while循環(huán)并不常用,但在模擬時(shí)常用,特別是在預(yù)先不知道迭代次數(shù)的情形。

二. apply函數(shù)族

apply函數(shù)族可以代替大部分的for循環(huán)、while循環(huán),其大意是“應(yīng)用(apply)”某函數(shù)(fun)到一系列的對(duì)象上。根據(jù)應(yīng)用到的對(duì)象的不同,是一族apply函數(shù)。

常用的有:

  • 分組計(jì)算:apply()和tapply()
  • 循環(huán)迭代:lapply()和sapply()
  • 多變量計(jì)算:mapply()
  • 函數(shù)apply()
  • apply()函數(shù)是最常用的代替for循環(huán)的函數(shù)。apply函數(shù)可以對(duì)矩陣、數(shù)據(jù)框、數(shù)組(二維、多維),按行或列進(jìn)行循環(huán)計(jì)算,對(duì)子元素進(jìn)行迭代,并把子元素以參數(shù)傳遞的形式給自定義的FUN函數(shù)中,并以返回計(jì)算結(jié)果。基本格式為:

    apply(x, MARGIN=..., fun, ...)

    其中,x為數(shù)據(jù)對(duì)象(矩陣、多維數(shù)組、數(shù)據(jù)框);

    MARGIN=1表示按行,2表示按列;

    fun表示要作用的函數(shù)。

    x<-matrix(1:6, ncol=3) x

    apply(x,1,mean) #按行求均值

    apply(x,2,mean) #按列求均值

    2. 函數(shù)tapply()

    按一組因子INDEX對(duì)數(shù)據(jù)列 x 分組,再分別對(duì)每組作用上函數(shù)fun。基本格式為:

    tapply(x, INDEX, fun, ..., simplify=TRUE)

    其中,x通常為向量;

    INDEX為與x長(zhǎng)度相同的因子列表(若不是因子,R會(huì)強(qiáng)制轉(zhuǎn)化為因子);

    simplify=TRUE且fun計(jì)算結(jié)果為標(biāo)量值,則返回值為數(shù)組,若為FALSE,則返回值為list對(duì)象

    dat <- data.frame(height=c(174,165,180,171,160), sex=c("F","F","M","M","F")) tapply(dat$height,dat$sex, mean) #計(jì)算分組均值: 不同sex對(duì)應(yīng)的height的均值

    3. 函數(shù)lapply()

    該函數(shù)是一個(gè)最基礎(chǔ)循環(huán)操作函數(shù),用來(lái)對(duì)vector、list、data.frame逐元、逐成分、逐列分別應(yīng)用函數(shù)fun,并返回和 x 長(zhǎng)度同樣的 list 作為結(jié)果。

    基本格式為:

    lapply(x, fun, ...)

    其中,x為數(shù)據(jù)對(duì)象(列表、數(shù)據(jù)框、向量)。

    x<-list(a=1:5, b=exp(0:3)) x

    lapply(x, mean)

    4. 函數(shù)sapply()

    sapply() 是 lapply() 的簡(jiǎn)化版本,多了一個(gè)參數(shù)simplify,若simplify=FALSE,則同lapply(),若為TRUE,則將輸出的list簡(jiǎn)化為向量或矩陣。基本格式為:

    sapply(x, fun, ..., simplify=TRUE, USE.NAMES=...)

    5. 函數(shù)mapply()

    是函數(shù)sapply()的多變量版本,將對(duì)多個(gè)變量的每個(gè)參數(shù)作用某函數(shù)。基本格式為:

    mapply(fun, ..., MoreArgs=NULL, SIMPLIFY=TRUE, USE.NAMES=TRUE)

    其中,

    MoreArgs為fun函數(shù)的其它參數(shù)列表;

    SIMPLIFY為邏輯值或字符串,取值為TRUR時(shí),將結(jié)果轉(zhuǎn)化為一個(gè)向量、矩陣或高維陣列(但不是所有結(jié)果都可轉(zhuǎn)化);

    ... 可以接收多個(gè)數(shù)據(jù),mapply將fun應(yīng)用于這些數(shù)據(jù)的第一個(gè)元素組成的數(shù)組,然后是第二個(gè)元素組成的數(shù)組,以此類推。

    返回值是vector或matrix,取決于fun返回值是一個(gè)還是多個(gè)。

    #重復(fù)生成列表list(x=1:2), 重復(fù)次數(shù)times=1:3,結(jié)果為列表 mapply(rep, times=1:3, MoreArgs = list(x=1:2))

    mapply(function(x,y) x^y, c(1:3), c(1:3))

    mapply(function(x,y) c(x+y, x^y), c(1:3), c(1:3))

    Alco <- data.frame(AlcoholDrunk=c("YES","YES","NO","YES","YES","YES",NA,"YES","YES","YES","YES","YES","YES","NO","NO","NO","NO","YES"), AmountDrunk=c(3.0, 1.0, NA ,3.0, NA, 0.0, NA, 0.0, NA, 1.7, NA, NA, 0.0, NA, NA, NA, NA, 2.0))

    其中,變量AlcoholDrunk有三種取值,“YES”表示有飲酒史;“NO”表示無(wú)飲酒史;NA表示數(shù)據(jù)不可獲取。

    定義alcohol()函數(shù)實(shí)現(xiàn)功能:若AlcoholDrunk是NA,直接返回NA;若是NO,返回NO;否則返回變量AmountDrunk的值。因?yàn)樾枰獋鬟f兩個(gè)變量的值,就需要用mapply()函數(shù):

    alcohol <- function(texVal, numVal){if(is.na(texVal)) {return("NA")}else if(texVal=="NO") {return("NO")}else if(is.na(numVal)) {return("amount Unknown")}else {return(numVal)} } mapply(alcohol, Alco$AlcoholDrunk, Alco$AmountDrunk)

    三. 泛型函數(shù)map

    泛型函數(shù),相當(dāng)于數(shù)學(xué)中的“泛函”,即函數(shù)的函數(shù)。

    “傳遞一個(gè)函數(shù)給另一個(gè)函數(shù)”是非常強(qiáng)大的思想,這也是R作為泛函型編程語(yǔ)言的表現(xiàn)之一。

    注:apply函數(shù)族也屬于泛型函數(shù)。

    purrr包,提供的函數(shù)足以代替許多通常的for循環(huán)。雖然apply函數(shù)族也能解決類似的問(wèn)題,但purrr包更具有一致性,從而也更容易學(xué)習(xí)。另外,purrr包還支持一些快捷用法,且所有函數(shù)都是用C語(yǔ)言寫的,速度更快。

    用purrr包的解決問(wèn)題的邏輯是:

    (1)針對(duì)列表每個(gè)單獨(dú)的元,你怎么解決某問(wèn)題?一旦你解決了該問(wèn)題,purrr包就可以將你的求解推廣到列表中的每一個(gè)元。

    (2)若你正在解決一個(gè)復(fù)雜問(wèn)題,你怎么把它分解成若干小問(wèn)題,使得你能夠逐步完成求解?用purrr包,你就可以將這些小問(wèn)題的求解步驟用管道組合到一起。

  • map函數(shù)族
  • “遍歷一個(gè)向量,對(duì)每個(gè)元做相同的操作,并保存結(jié)果”,這種循環(huán)模式是如此常見,所以purrr包提供了一族map函數(shù)來(lái)做這件事。一個(gè)函數(shù)針對(duì)一種類型的輸出:

    • map()—映射列表,基本等同于lapply()
    • map_lgl()—映射邏輯向量
    • map_int()—映射整數(shù)型向量
    • map_dbl()—映射浮點(diǎn)數(shù)向量
    • map_chr()—映射字符型向量

    每個(gè)函數(shù)都接受一個(gè)輸入向量,應(yīng)用一個(gè)函數(shù)到每一個(gè)元,再返回與輸入向量同名同長(zhǎng)度的新向量;向量的類型由map函數(shù)的后綴所確定。

    注:map_*()函數(shù)必須接受原子向量,可以是行、列向量。

    例如,對(duì)前文的 數(shù)據(jù)框 df,

    map_dbl(df, mean)

    map_dbl(df, median)

    map_dbl(df, sd)

    與用for循環(huán)相比,map函數(shù)是聚焦在所執(zhí)行的操作(mean(), median(), sd()),而不是循環(huán)遍歷每個(gè)元并存儲(chǔ)結(jié)果。若改用管道操作更明顯:

    df %>% map_dbl(mean) df %>% map_dbl(median) df %>% map_dbl(sd)

    2. 多變量迭代的map函數(shù)

    前面map函數(shù)族實(shí)現(xiàn)的都是對(duì)一個(gè)向量(單變量的數(shù)據(jù))進(jìn)行迭代操作。實(shí)際中,經(jīng)常會(huì)用到針對(duì)多個(gè)變量進(jìn)行并行迭代,這就需要用map2()或pmap()函數(shù)。

    (1)兩個(gè)變量的迭代:map2()

    例如,根據(jù)

    和 不同的參數(shù)組合,生成正態(tài)分布隨機(jī)數(shù):

    mu = c(5,10,-3) sigma = c(1,5,10) map2(mu, sigma, rnorm, n = 5)

    前文的mapply例子,也可以用map2來(lái)實(shí)現(xiàn):

    unlist(map2(Alco$AlcoholDrunk, Alco$AmountDrunk,alcohol))

    (2)更多個(gè)變量迭代:pmap()

    前面都是隨機(jī)生成5個(gè)數(shù),讓個(gè)數(shù)也變起來(lái):

    n <- c(1,3,5) args <- list(mean = mu, sd = sigma, n = n) pmap(args, rnorm)

    主要參考文獻(xiàn):

  • R for Data Science. Hadley Wickham, Garrett Grolemund,O'Reilly, 2017.
  • 張良均,謝佳標(biāo),楊坦,肖剛. R語(yǔ)言與數(shù)據(jù)挖掘. 機(jī)械工業(yè)出版社,2016.
  • mapply函數(shù)?www.jianshu.com

    原創(chuàng)作品,轉(zhuǎn)載請(qǐng)注明。

    總結(jié)

    以上是生活随笔為你收集整理的pycharm中配置r语言_【R语言】R语言中的循环的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。