【问题标题】:R - if else taking too long for 16 million rowsR - 如果其他 1600 万行的时间太长
【发布时间】:2021-12-29 03:48:00
【问题描述】:

我有一个包含 1600 万行的数据框,我希望在现有列 Month 的基础上添加一列。如果月份是 3 或 4 或 5,列 Season 将为 spring 等。

for (i in 1:nrow(df)) {
    if (df$Month[[i]] %in% c(3,4,5)) {
        df$Season[[i]] <- "Spring"
    } else if (df$Month[[i]] %in% c(6,7,8)) {
        df$Season[[i]] <- "Summer"
    } else if (df$Month[[i]] %in% c(9,10,11)) {
        df$Season[[i]] <- "Autumn"
    } else if (df$Month[[i]] %in% c(12,1,2)) {
        df$Season[[i]] <- "Winter"
    }
}

但是,它需要很长时间才能完成。我能做什么?

【问题讨论】:

  • 对于这么大的数据帧,尽量不要使用 for 循环。总有一个矢量化的替代方案。

标签: r


【解决方案1】:

一种更简单快捷的方法是创建月份和季节的数据框,然后将其加入您的父数据框。

像这样:

seasons<-data.frame(Month=1:12, Season=c("Winter", "Winter", rep("Spring", 3), rep("Summer", 3), rep("Autumn", 3), "Winter"))

answer <- dplyr::left_join(df, seasons)

这是假设两个数据框都有匹配的列名“月”。

我预计性能比for 循环提高约 1000 倍。

【讨论】:

    【解决方案2】:

    这更符合@Dave2e 的行,但带有基数 R:

    Season=c("Winter", "Winter", rep("Spring", 3),
            rep("Summer", 3), rep("Autumn", 3), "Winter")
    df<-data.frame(month=sample(1:12,10,replace=T)) #Sample data
    df$season<-Season[df$month]
    df
    #   month season
    #1      8 Summer
    #2      8 Summer
    #3      5 Spring
    #4      7 Summer
    #5      2 Winter
    #6      4 Spring
    #7     12 Winter
    #8      7 Summer
    #9     11 Autumn
    #10     1 Winter
    

    这个,明显比for循环方法快。

    使用for 循环(1000 行):

       #user  system elapsed 
       #0.02    0.00    0.02
    

    使用矢量化方法(1000 行):

       #user  system elapsed 
       #   0       0       0
    

    使用system.time 计算。

    考虑到只有 1000 行,这种差异可能看起来微不足道。但是,随着行数的增加(在 OP 的情况下为 1600 万),它变得非常大

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-16
      • 2020-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-20
      • 1970-01-01
      相关资源
      最近更新 更多