【问题标题】:Computing Variables in R from Multiple Values in the Same Variable从同一变量中的多个值计算 R 中的变量
【发布时间】:2016-07-20 23:18:47
【问题描述】:

假设我们有一个名为 df 的数据集,并且该数据集由名为 year 和 x1 的两个变量组成:

year <- c(2000, 2001, 2002, 2003, 2004)
x1 <- c(7, 8, 6, 3, 3)
df <- data.frame(year, x1)

我的任务是计算 x1 中的两个新变量。第一个变量是 cSum,它必须反映过去两年 x1 值的总和。第二个变量是 cMax,它必须反映过去三年中 x1 的最高值。

结果应该如下:

year  x1  cSum  cMax
2000   7     
2001   8    15     
2002   6    14     8
2003   3     9     8
2004   3     6     6

如何计算上面的 cSum 和 cMax 变量?

谢谢!

【问题讨论】:

    标签: r variables recode


    【解决方案1】:

    使用data.table

    library(data.table)
    setDT(df)
    

    首先,一种复杂的方式;由于transpose 已经过优化,这可能会更快(未经测试):

    df[ , cSum := transpose(lapply(transpose(shift(x1, 0:1)), sum))]
    df[ , cMax := transpose(lapply(transpose(shift(x1, 0:2)), max))]
    

    shift本质上是一个滞后算子;我们希望滞后 0、1 和(对于cMax)2 来获取当前和之前的 1(或 2)个周期。

    或者:

    df[ , cSum := rowSums(do.call(cbind, shift(x1, 0:1)))]
    df[ , cMax := do.call(pmax, shift(x1, 0:2))]
    

    两者都给出相同的输出:

    df
    #    year x1 cSum cMax
    # 1: 2000  7   NA   NA
    # 2: 2001  8   15   NA
    # 3: 2002  6   14    8
    # 4: 2003  3    9    8
    # 5: 2004  3    6    6
    

    让这个混乱的事情是当shift返回一个以上的滞后时,它返回一个list;但不幸的是,这个列表是我们需要的转置(我们正在执行逐行操作,并且它是以列友好的方式生成的)。第一个选项transposes 将列表以更易于管理的形式获取,然后在transpose返回列形式之前执行逐行操作。

    第二个选项将输出转换为数组并对数组进行逐行操作。

    【讨论】:

    • is transpose 需要,这将实现相同的df[,cSum:=(shift(x1,1,"lag")+shift(x1,2,"lag"))]
    • @Bg1850 我实际上是要补充的,谢谢指出。这种方法不是很可扩展(例如,总计 10 个周期),但在这种情况下肯定更令人愉快。
    • 谢谢!如果可能的话,还有一件事:如果我想在没有滞后的情况下执行此操作,我应该如何编辑代码?也就是说,以某种方式应该导致 NA 值到达列的底部,而不是顶部?
    • 你的意思是领先而不是落后?简单地否定索引。
    • 我试过了。但负数 (0:1) 会返回错误。
    【解决方案2】:

    这是一种利用滞后运算符的方法。本质上,我是在扩充您的数据,以尽量减少对 for 循环的需求。这样做,我正在增加使用的内存量。如果您要使用此数据集进行更多时间序列分析,这种方法可能有意义。在答案中,我使用了zoo 包,这是我最喜欢的时间序列包。不过还有很多其他的tsxts(一般比zoo快)、...

    library(zoo)
    
    year <- c(2000, 2001, 2002, 2003, 2004, 2005)
    x1 <- c(7, 8, 6, 3, 3, 6)
    df <- data.frame(year, x1)
    
    dfZ <- zoo(df[,-1], order.by = df[,1]) 
    
    dfZ <- merge(dfZ, lag(dfZ, seq(-1, -2)))
    
    names(dfZ) <- paste0("L", seq(0,2))
    
    dfZ$cSum <- rowSums(dfZ[, c("L0", "L1")])
    dfZ$cMax <- apply(dfZ[, c("L0", "L1", "L2")], 1, max)  
    

    【讨论】:

      猜你喜欢
      • 2018-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-09
      • 1970-01-01
      • 1970-01-01
      • 2014-11-19
      相关资源
      最近更新 更多