【问题标题】:Calculate number of rows of each new dataframe from loop and save everything in one loop从循环中计算每个新数据帧的行数并将所有内容保存在一个循环中
【发布时间】:2021-09-19 21:39:50
【问题描述】:

我创建了以下循环,过滤了我每年(81 到 91 之间)的数据,并从每次迭代中创建一个新的数据框。

for(i in 81:91){
  assign(paste0("SampleSizeGaza",i), GazaTB1[GazaTB1$year==i,])
}

有什么办法可以修改这个循环(或创建一个新的循环)来计算每个新数据项的行数(最好使用 nrows)并将其保存到一个数据帧(例如 SampleSize)上两列,分别是年份(从 81 到 91)和 YearSampleSize(每年每个数据帧的 nrow)。 任何帮助表示赞赏

【问题讨论】:

    标签: r dataframe for-loop


    【解决方案1】:
    df <- data.frame()
    for(i in 81:91){
      assign(paste0("SampleSizeGaza",i), GazaTB1[GazaTB1$year==i,])
      dfi <- data.frame(year = i, YearSampleSize = NROW(eval(as.name(paste0("SampleSizeGaza", i)))))
      df <- rbind(df, dfi)
    }
    

    一切都在 base R 中,但是我确实需要提到,与使用 dplyr/tidyverse 相比,这非常低效。这是一个非常大的数据框的比较:

    > ### Create large dataframe
    > GazaTB1 <- data.frame(year = sample(81:91, size = 50000000, replace = TRUE))
    
    > ### for loop
    > ptm <- proc.time()
    > df <- data.frame()
    > for(i in 81:91){
    +   assign(paste0("SampleSizeGaza",i), GazaTB1[GazaTB1$year==i,])
    +   dfi <- data.frame(year = i, YearSampleSize = NROW(eval(as.name(paste0("SampleSizeGaza", i)))))
    +   df <- rbind(df, dfi)
    + }
    > proc.time() - ptm
       user  system elapsed 
       2.80    1.27    4.08 
    > 
    > ### tidyverse
    > library(tidyverse)
    > 
    > ptm2 <- proc.time()
    > df2 <- GazaTB1 %>% 
    +   group_by(year) %>% 
    +   count()
    > proc.time() - ptm2
       user  system elapsed 
       0.64    0.14    0.78 
    

    【讨论】:

    • 谢谢!您发布的第一个代码完美运行
    【解决方案2】:

    如果您将数据保存在一个对象中,而不是使用assign 创建多个对象,则分组操作更易于管理。有两种常见的方法可以做到这一点。

    基础 R

    以下代码使用split 将数据框拆分为一个列表,其中数据框“组”列的每个唯一值都有一个单独的数据框,然后使用sapply 计算列表中的行数。结果是一个命名向量。

    df <- data.frame(
      group = sample(letters[1:4], 100, replace = T),
      value = rnorm(100)
    )
    
    head(df)
      group      value
    1     a  0.3691390
    2     b -0.2444268
    3     d -0.4776481
    4     b -1.5580131
    5     a  1.1913923
    6     a -2.1483141
    
    df.split <- split(df, df$group)
    counts <- sapply(df.split, nrow)
    
     a  b  c  d 
    24 28 16 32 
    

    Tidyverse

    或者,我们可以使用 tidyverse 包直接对数据框执行分组操作,返回汇总数据框:

    library(tidyverse)
    
    df.counts <- df %>% 
      group_by(group) %>% 
      count()
    
      group     n
      <chr> <int>
    1 a        24
    2 b        28
    3 c        16
    4 d        32
    

    【讨论】:

      猜你喜欢
      • 2016-10-05
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2018-03-15
      • 2019-10-09
      • 1970-01-01
      • 2019-09-30
      • 1970-01-01
      相关资源
      最近更新 更多