【问题标题】:Conditionally fill column by other columns values有条件地用其他列值填充列
【发布时间】:2017-01-08 09:34:55
【问题描述】:

我有大约 400 万行个人数据,如下所示:

names <- c("Peter", "Peter", "Peter", "Peter", "Peter", "Peter", "Peter", "Lisa", "Bert", "Carine", "Carine", "Carine", "Carine", "Carine", "Carine")
luckyToday <- c(0,0,0,NA,0,0,1,NA,1,NA,0,0,0,1,1)
luckyYesterday <- NA_real_
df1 <- data.frame(names,luckyToday,luckyYesterday)

df1
# names luckyToday luckyYesterday
# 1   Peter          0             NA
# 2   Peter          0             NA
# 3   Peter          0             NA
# 4   Peter         NA             NA
# 5   Peter          0             NA
# 6   Peter          0             NA
# 7   Peter          1             NA
# 8    Lisa         NA             NA
# 9    Bert          1             NA
# 10 Carine         NA             NA
# 11 Carine          0             NA
# 12 Carine          0             NA
# 13 Carine          0             NA
# 14 Carine          1             NA
# 15 Carine          1             NA

数据包含对人们的观察(有些观察到 1 次,有些观察到更多)和他们的幸运(1=幸运,0=不幸,NA=无信息)。作为一种滞后变量,我想引入一个新变量(“luckyYesterday”),它告诉我这个人在上次观察期间是否幸运。所以我希望数据看起来像这样:

df2
# names luckyToday luckyYesterday
# 1   Peter          0             NA
# 2   Peter          0              0
# 3   Peter          0              0
# 4   Peter         NA              0
# 5   Peter          0              0
# 6   Peter          0              0
# 7   Peter          1              0
# 8    Lisa         NA             NA
# 9    Bert          1             NA
# 10 Carine         NA             NA
# 11 Carine          0              0
# 12 Carine          0              0
# 13 Carine          0              0
# 14 Carine          1              0
# 15 Carine          1              1

我知道 R 不是应用这种数据处理的完美程序,但它是必要的。

我想考虑以下几点:

  1. 考虑到这些是我所观察到的独一无二的人,不要混淆对不同人的观察。
  2. 较低的观测值较新。对独特人物的最后一次观察是最新的(第 7 行是对彼得的最新观察)。
  3. 如果“luckyToday”列(例如第 4 行)中有 NA,我不希望相应的“luckyYesterdayNA”(第 5 行)也填充 NA。我宁愿希望相应的单元格填充“luckyToday”列中最新的“non-NA”观察值,在示例数据中它是“0”。如果之前的观察只是 NA,那么我假设它们等于最新的观察。 (如果我有 9 个 NA 并且第 10 个观测值是“1”,那么我想假设观测值 1-9 也是“1”。
  4. 如果每个人只有一个观察值,我希望在“luckyYesterday”列中无论如何都有一个 NA,因为我不知道之前的运气状态。

我自己尝试了 2 个 for 循环,但我对数据的观察时间超过了 400 万次。谁能帮助我提供更快的解决方案,例如 data.table 或 apply 函数?非常感谢!

干杯

【问题讨论】:

    标签: r data.table conditional


    【解决方案1】:

    您可以使用data.table 中的shift 函数来观察昨天,并使用zoo 包中的na.locf 函数根据fromLast 参数是F 还是T 来填充昨天或明天的NA,以及如果您不想混合对不同人的观察,请按名称分组:

    library(data.table); library(zoo)
    setDT(df1)[,luckyYesterday := shift(na.locf(luckyToday, fromLast = TRUE)), names]
    
    df1
    #      names luckyToday luckyYesterday
    #  1:  Peter          0             NA
    #  2:  Peter          0              0
    #  3:  Peter          0              0
    #  4:  Peter         NA              0
    #  5:  Peter          0              0
    #  6:  Peter          0              0
    #  7:  Peter          1              0
    #  8:   Lisa         NA             NA
    #  9:   Bert          1             NA
    # 10: Carine         NA             NA
    # 11: Carine          0              0
    # 12: Carine          0              0
    # 13: Carine          0              0
    # 14: Carine          1              0
    # 15: Carine          1              1
    

    【讨论】:

    • 或者data.table中na.locf的常见替代方法:cumsum with !is.na:df1[.N:1, luckyFill := luckyToday[1L], by=.(names, cumsum(!is.na(luckyToday)))]; df1[, luckyYest := shift(luckyFill), by=names] 但是,这需要分组两次,所以我怀疑na.locf更好。
    • @Frank 从未测试过na.locf 的速度。 cumsum 通常很快。所以不确定哪个实际上更快。
    【解决方案2】:
    names <- c("Peter", "Peter", "Peter", "Peter", "Peter", "Peter", 
        "Peter", "Lisa", "Bert", "Carine", "Carine", "Carine", "Carine", "Carine", "Carine")
    luckyToday <- c(0,0,0,NA,0,0,1,NA,1,NA,0,0,0,1,1)
    luckyYesterday <- NA
    df1 <- data.frame(names,luckyToday,luckyYesterday)
    
    # New code
    library(data.table) 
    data.table(df1)[,list(luckyToday, c(NA, luckyToday[1:(.N-1)])),by=list(names)]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-14
      • 1970-01-01
      • 1970-01-01
      • 2020-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-19
      相关资源
      最近更新 更多