【问题标题】:Split a large dataframe into multiple dataframes by row in R在R中按行将大数据帧拆分为多个数据帧
【发布时间】:2020-12-14 15:06:44
【问题描述】:

我有一个大型数据框,其中包含超过 1m 条记录和 40 多个变量,我想通过循环运行值更新以防止出现故障,并且文件的大小每次都不同。我想将超过 1m 行分成 n 个较小的集合,每个集合都有一个新的数据框名称,例如以 1,2,...,n, newdf1, newdf2, newdf3,... 结尾。 R 中的拆分函数仅拆分向量,但它仍在该数据帧中,而不是创建数据帧的多个子集,我需要在 40 个变量中保留数据类型。我没有要按列拆分的值,我只想按行号按顺序拆分。

【问题讨论】:

  • 您可以使用split.. 如果您显示示例,更容易知道split中的问题究竟是什么
  • 我试过了,但它没有创建新的多个数据框。我想索引列中的值。
  • 请展示一个可重现的小例子和预期的输出
  • 如果你想要n行组中的数据框,每个尝试split(df, seq(nrow(df)) %/% n)

标签: r dataframe split subset


【解决方案1】:

这是一个示例,我们生成一个包含 100 万行的数据框,将其分成 20 组,在结果列表中命名数据框,然后在列表中的第一个数据框上运行 summary(),方法是使用$ 运算符的名称。

set.seed(90125)
df <- as.data.frame(matrix(rnorm(40000000,mean = 25,sd=5),ncol=40))
# make group number start with 1, as remainders
# vary from 0 - 19
df$group <- 1:1000000 %% 20 + 1
dfList <- split(df,df$group)

此时内存中有两个数据副本:原始数据帧df,第二个副本在dfList列表中被分成20个不同的数据帧。

我们可以用length() 函数来证明这一点:

> length(dfList)
[1] 20

每个数据框有 50,000 个观察值,我们可以使用 nrow() 函数来演示:

> nrow(dfList[[1]])
[1] 50000

我们可以使用names()paste0() 的组合为数据框指定名称。

# add names to the list and print the names
names(dfList) <- paste0("data",1:20)
names(dfList)
> names(dfList)
 [1] "data1"  "data2"  "data3"  "data4"  "data5"  "data6"  "data7"  "data8" 
 [9] "data9"  "data10" "data11" "data12" "data13" "data14" "data15" "data16"
[17] "data17" "data18" "data19" "data20"

一旦数据帧被命名,就可以通过提取运算符的$ 形式从列表中访问它们。我们将生成第一个数据框的摘要,并按名称访问它。

summary(dfList$data1[1:5])

...和输出:

> summary(dfList$data1[1:5])
       V1                V2               V3              V4        
 Min.   :-0.7251   Min.   : 2.481   Min.   : 3.02   Min.   : 3.173  
 1st Qu.:21.5919   1st Qu.:21.603   1st Qu.:21.57   1st Qu.:21.526  
 Median :24.9990   Median :24.982   Median :24.97   Median :24.914  
 Mean   :24.9968   Mean   :24.978   Mean   :24.97   Mean   :24.931  
 3rd Qu.:28.3971   3rd Qu.:28.330   3rd Qu.:28.32   3rd Qu.:28.357  
 Max.   :45.7101   Max.   :44.730   Max.   :48.03   Max.   :45.506  
       V5        
 Min.   : 2.427  
 1st Qu.:21.595  
 Median :25.010  
 Mean   :24.997  
 3rd Qu.:28.406  
 Max.   :44.199  
> 

注意:原始数据帧大约消耗312.8Mb,所以在执行split()函数后,两份数据将消耗大约625.6Mb的RAM。如有必要,可以使用rm() 函数从 RAM 中删除原始数据帧。

【讨论】:

  • 嗨,如果我想做同样的事情,但要使用列。例如,我有一个有 105 列的 df。我想创建 10 个小的 df,每个有 15 列,但前 5 列将出现在所有小的 dfs 中。我需要做什么?
  • @zillurrahman -- 您可以使用提取运算符选择要包含在输出数据帧中的列,例如df[,1:5]
【解决方案2】:

没有看到带有一些示例数据的最小可重复示例,我想我对您要完成的工作有所了解。假设您有一个 10000 行的数据集,并且希望将您的数据拆分为每个 100 行的单独数据帧。您可以根据您希望较小数据帧的长度将较大的数据帧子集到较小数据帧的列表中。


####  Some dummy data here ####
colA <- rep(c("X1", "X2", "X3", "X4", "X5"), 2000)
colB <- rnorm(n = 10000, mean = 3, sd = 0.25)
colC <- rnorm(n = 10000, mean = 1, sd = 1)

df <- as.data.frame(cbind(colA, colB, colC), stringsAsFactors = FALSE)

#### Create an empty list to be filled with your subset data frames ####
dataList <- list()

#### Since it's 10000 rows total, and you want 100 smaller data frames, ####
#### create an iterator variable that you can reference for subsetting. ####
listIterator <- seq(0,99,1)

for(i in listIterator){
  dataList[[i+1]] <- df[c((1+(100*i)):(100+(100*i))),]  
}

dataList[1]
dataList[2]

然后,您可以将数据框列表子集化为您将在特定时间使用的任何数据框。 . .

df1 <- dataList[1]

或引用每个列中的特定列

dataList[[1]]$colA

【讨论】:

  • 值得一提的是使用 purrr::map() 命令来处理这种列表
猜你喜欢
  • 2013-11-16
  • 1970-01-01
相关资源
最近更新 更多