【问题标题】:for loop question in R with rbind or do.call使用 rbind 或 do.call 在 R 中的 for 循环问题
【发布时间】:2021-08-14 05:43:32
【问题描述】:

我的数据集的一个非常简化的示例:

         HUC8 YEAR RO_MM
   1: 10010001 1961  78.2
   2: 10010001 1962  84.0
   3: 10010001 1963  70.2
   4: 10010001 1964 130.5
   5: 10010001 1965  54.3

我在网上找到了这段代码,但不是完全符合我的要求:

#create a list of the files from your target directory

file_list <- list.files(path="~/Desktop/Rprojects")

#initiate a blank data frame, each iteration of the loop will append the data from the given file to this variable

allHUCS <- data.frame()

#I want to read each .csv from a folder named "Rprojects" on my desktop into one huge dataframe for further use.

for (i in 1:length(file_list)){
  temp_data <- fread(file_list[i], stringsAsFactors = F) 
  allHUCS <- rbindlist(list(allHUCS, temp_data), use.names = T) 
}

问题:我读到不应将 rbindlist 用于大型数据集:

“你永远不应该在循环中迭代 rbind:一开始性能可能还不错,但是每次调用 rbind 都会生成一个完整的数据副本,因此每次传递时要复制的总数据都会增加。它可怕地扩展。考虑 do.call(rbind.data.frame, file_list)。" – @r2evans

我知道这可能看起来很简单,但我不清楚如何使用他的指令。我会在最后一行写这个吗?

allHUCS <- do.call(rbind.data.frame(allHUCS, temp_data), use.names = T)

还是别的什么?在我的实际数据中,每个 .csv 有 2099 个对象和 3 个变量(但我只关心最后两个。)总数据框应该包含 47,000,000+ 个对象的 2 个变量。当我运行原始代码时,我得到了这些错误:

rbindlist(list(allHUCS, temp_data), use.names = T) 中的错误:第 2 项 有 2 列,与有 3 列的项目 1 不一致。填写 缺少的列使用 fill=TRUE。

另外:警告消息:1:在 fread(file_list[i], stringsAsFactors = F) : 检测到 1 个列名,但数据有 2 个 列(即无效文件)。为 第一列被猜测为行名或索引。采用 setnames() 如果这个猜测不正确,或者修复文件 写入创建文件的命令以创建有效文件。

2:在 fread(file_list[i], stringsAsFactors = F) 中:提前停止 第 20 行。预期 2 个字段,但找到 3。考虑 fill=TRUE 和 评论.char=。第一个丢弃的非空行: >

除了setnames() 的建议,我不明白别人告诉我什么。我知道它说它提前停止了,但我什至不知道如何查看整个数据集或判断它停止的位置。

我现在读到 rbindlist 和 rbind 是两个不同的东西,rbindlist 比 do.call(rbind, data) 快。但建议是 do.call(rbind.data.frame(allHUCS, temp_data)。哪个最快?

【问题讨论】:

  • 你需要do.call(rbind, lapply(file_list, fread))
  • 或者,如果您已经在使用 data.table 函数,只需执行 rbindlist(lapply(file_list, fread)) 。您引用的 cmets 的全部要点是 R 中增长的对象可能效率低下。因此最好立即对孔对象执行任何操作,而不是在for loop 中。您收到的错误/警告表明您正在阅读的所有文件可能没有相同的标题。为了安全起见,首先将所有内容都读入列表中,然后担心以后将它们绑定在一起,df_list &lt;- lapply(fille_list, fread); lapply(df_list, colnames) #inspect output
  • @JustinLandis 对它们的随机抽样显示它们是相同的:名为 HUC8、YEAR、RO_MM 的三列。所有 344,000 多个 csv 文件都是在同一操作中创建的。他们仍然有可能有不同的标题吗?另外,您能否解释一下rbindlist(lapply(file_list, fread)) 将适合我的代码,而不是哪一行,或者它代替整个for循环?我真的很陌生。
  • 这将替换整个循环。 lapply 函数会将第二个参数(一个函数)应用于第一个参数的每个元素,并以列表的形式返回结果。然后rbindlist 会将它们合并为一个data.frame。至于警告,在您阅读所有内容之前,您可能不知道问题是什么。只需分两步完成。祝你好运
  • 关于框架列表的一个很好的讨论在这里:stackoverflow.com/a/24376207/3358227。虽然该讨论经常偏离将框架保留为列表中的唯一元素,但它确实涉及如何组合它们。

标签: r data.table rbind do.call


【解决方案1】:

由于原始帖子不包含可重现的示例,因此这里是从我在 Github 上维护的 Pokémon Stats data 读取数据的示例。

首先,我们为每一代神奇宝贝下载一个包含一个 CSV 文件的 zip 文件,并将其解压缩到 R 工作目录的 ./pokemonData 子目录。

download.file("https://raw.githubusercontent.com/lgreski/pokemonData/master/PokemonData.zip",
          "pokemonData.zip",
          method="curl",mode="wb")

unzip("pokemonData.zip",exdir="./pokemonData")

接下来,我们获取解压 CSV 文件所在目录中的文件列表。

thePokemonFiles <- list.files("./pokemonData",
                              full.names=TRUE) 

最后,我们加载data.table包,使用lapply()data.table::fread()读取文件,将生成的数据表列表与do.call()结合起来,打印出head()和`tail()包含所有 8 代神奇宝贝统计数据的结果数据框。

library(data.table)

data <- do.call(rbind,lapply(thePokemonFiles,fread))

head(data)
tail(data)

...和输出:

> head(data)
   ID       Name Form Type1  Type2 Total HP Attack Defense Sp. Atk Sp. Def Speed
1:  1  Bulbasaur      Grass Poison   318 45     49      49      65      65    45
2:  2    Ivysaur      Grass Poison   405 60     62      63      80      80    60
3:  3   Venusaur      Grass Poison   525 80     82      83     100     100    80
4:  4 Charmander       Fire          309 39     52      43      60      50    65
5:  5 Charmeleon       Fire          405 58     64      58      80      65    80
6:  6  Charizard       Fire Flying   534 78     84      78     109      85   100
   Generation
1:          1
2:          1
3:          1
4:          1
5:          1
6:          1
> tail(data)
    ID      Name         Form   Type1 Type2 Total  HP Attack Defense Sp. Atk
1: 895 Regidrago               Dragon         580 200    100      50     100
2: 896 Glastrier                  Ice         580 100    145     130      65
3: 897 Spectrier                Ghost         580 100     65      60     145
4: 898   Calyrex              Psychic Grass   500 100     80      80      80
5: 898   Calyrex    Ice Rider Psychic   Ice   680 100    165     150      85
6: 898   Calyrex Shadow Rider Psychic Ghost   680 100     85      80     165
   Sp. Def Speed Generation
1:      50    80          8
2:     110    30          8
3:      80   130          8
4:      80    80          8
5:     130    50          8
6:     100   150          8
> 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    • 2016-08-20
    • 2020-02-03
    相关资源
    最近更新 更多