【问题标题】:How to do this in R如何在 R 中做到这一点
【发布时间】:2017-05-15 20:19:06
【问题描述】:

我有一个如下所示的数据集:

groups <- c(1:20)
A <- c(1,3,2,4,2,5,1,6,2,7,3,5,2,6,3,5,1,5,3,4)
B <- c(3,2,4,1,5,2,4,1,3,2,6,1,4,2,5,3,7,1,4,2)
position <- c(2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1)
sample.data <- data.frame(groups,A,B,position)
head(sample.data)
      groups     A       B     position
  1      1       1       3        2
  2      2       3       2        1
  3      3       2       4        2
  4      4       4       1        1
  5      5       2       5        2
  6      6       5       2        1

“位置”列总是在 2 和 1 之间交替。我想在 R 中进行此计算:从第一行开始,如果它在位置 1,则忽略它。如果它从 2 开始(如本例所示),则计算如下:

  • 取 A 列中位于位置 2 的前 2 个值,将它们平均,然后减去位于位置 1 的第一个值(在本例中:(1+2)/2 - 3 = -1.5)。然后对下一组值重复计算,使用最后一个位置 2 值作为起点,即下一个计算将是 (2+2)/2 - 4 = -2。
  • 所以基本上,在这个例子中,计算是针对这些组的值进行的:1-2-3、3-4-5、5-6-7 等(上一个的最后一个值是下一组计算的第一个值)
  • 重复计算直到结束。也对 B 列执行相同操作。
  • 由于我需要完整的原始数据框,将新计算的值放入一个新的数据框中,dA 和 dB 列分别对应 A 列和 B 列的计算值(如果不可能,那么它们可以被创建为单独的数据帧,然后我会将它们提取到一个中)。

期望的输出(来自示例):

    dA    dB
1  -1.5  1.5
2   -2   3.5
3  -3.5  2.5
4  -4.5  2.5
5  -4.5  2.5
6  -2.5   4

【问题讨论】:

    标签: r calculation


    【解决方案1】:
    groups <- c(1:20)
    A <- c(1,3,2,4,2,5,1,6,2,7,3,5,2,6,3,5,1,5,3,4)
    B <- c(3,2,4,1,5,2,4,1,3,2,6,1,4,2,5,3,7,1,4,2)
    position <- c(2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1)
    sample.data <- data.frame(groups,A,B,position)
    
    start <- match(2, sample.data$position)
    twos <- seq(from = start, to = nrow(sample.data), by = 2)
    
    df <- 
      sapply(c("A", "B"), function(l) {
        sapply(twos, function(i) { 
          mean(sample.data[c(i, i+2), l]) - sample.data[i+1, l]
        })
      })
    
    df <- setNames(as.data.frame(df), c('dA', 'dB'))
    

    【讨论】:

      【解决方案2】:

      由于position 中的值始终在 1 和 2 之间交替,您可以定义奇数行索引i1 和偶数行索引i2,然后进行计算:

      ## In case first row has position==1, we add an increment of 1 to the indexes
      inc=0
      if(sample.data$position[1]==1)
      {inc=1}
      i1=seq(1+inc,nrow(sample.data),by=2)
      i2=seq(2+inc,nrow(sample.data),by=2)
      res=data.frame(dA=(lead(sample.data$A[i1])+sample.data$A[i1])/2-sample.data$A[i2],
      dB=(lead(sample.data$B[i1])+sample.data$B[i1])/2-sample.data$B[i2]);
      

      这会返回:

      dA  dB
      1  -1.5 1.5
      2  -2.0 3.5
      3  -3.5 2.5
      4  -4.5 2.5
      5  -4.5 2.5
      6  -2.5 4.0
      7  -3.5 2.5
      8  -3.0 3.0
      9  -3.0 4.5
      10   NA  NA
      

      最后一行返回NA,如果需要可以去掉。

      res=na.omit(res)
      

      【讨论】:

      • 我注意到在您的代码中,if 语句以“如果第一个位置是 2”开头。如果样本从位置 1 开始会发生什么?它会忽略第一行,还是不起作用?谢谢
      • 我以为您只想在第一行包含 2 时才进行计算。但也许您想从包含 2 的第一行开始进行计算,如果第一行包含 1,则离开它没有改变,对吗?我已更改答案以反映这一点。
      • 是的,很抱歉造成混乱。也许我应该说“忽略第一行”,而不是“忽略它”。如果数据从位置 1 开始,则离开该行,并从位置 2 的第一行(即下一行)开始执行计算。附言我没有看到更改,您保存了编辑,还是仍在编辑?谢谢
      • 我想我现在明白你想要什么了。我已经编辑了答案。
      猜你喜欢
      • 1970-01-01
      • 2014-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-26
      • 2019-07-25
      相关资源
      最近更新 更多