【问题标题】:How can I compare a value in a column to the previous one using R?如何使用 R 将列中的值与前一个值进行比较?
【发布时间】:2013-03-05 22:22:00
【问题描述】:

我在 R 中有一个由 4 列和数千行组成的大型数据框。 这里以第一行为例:

     ID     V1      V2     Stimulus
[1,]  001   74.80   803.0   0
[2,]  001   75.98   790.9   0
[3,]  001   75.95   791.1   0
[4,]  001   65.70   918.7   0
[5,]  001   59.63   1005.6  13
[6,]  001   59.44   1012.0  13
[7,]  001   59.62   1010.0  13
[8,]  001   63.85   942.4   13
[9,]  001   60.75   992.9   0
[10,] 001   59.62   1010.0  0
[11,] 001   61.68   974.0   0
[12,] 001   65.21   921.4   15
[13,] 001   59.23   1012.0  15
[14,] 001   61.23   979.5   15
[15,] 001   70.80   849.2   0

在此数据框中,每一行对应 1 秒。第 4 列(刺激)是 0(即无刺激)或大于 0 的正整数(即刺激数)。刺激数字总是由一个或多个 0 值分隔)。

我想了解如何将第 4 列(刺激)中的每个数值与前一行中的值进行比较:从这个比较中,我想在数据框中创建第 5 列,我在其中编写“PRE " 如果值为 0,则在值更改时(但仅针对前 2 行/秒)为“OK”,并且在再次显示新的 0 值之前,对于不同于 0 的其余数字行,“POST”。

这是我想从上一个数据帧中获取的示例

         ID     V1      V2     Stimulus    Status
    [1,]  001   74.80   803.0   0           PRE
    [2,]  001   75.98   790.9   0           PRE
    [3,]  001   75.95   791.1   0           PRE
    [4,]  001   65.70   918.7   0           PRE
    [5,]  001   59.63   1005.6  13          OK
    [6,]  001   59.44   1012.0  13          OK
    [7,]  001   59.62   1010.0  13          POST
    [8,]  001   63.85   942.4   13          POST
    [9,]  001   60.75   992.9   0           PRE
    [10,] 001   59.62   1010.0  0           PRE
    [11,] 001   61.68   974.0   0           PRE
    [12,] 001   65.21   921.4   15          OK
    [13,] 001   59.23   1012.0  15          OK
    [14,] 001   61.23   979.5   15          POST
    [15,] 001   70.80   849.2   0           PRE

请注意,在第 7,8 和 14 行中,我有值“POST”(当检测到值从 0 发生变化时,OK 值仅归因于前 2 行)。

我不确定如何解决这个问题。我的想法如下: 我应该遍历数据框第 4 列中的每一行。对于每一行 i 我应该检查它是否大于上一行

 mydataframe$Stimulus[i,4] >  mydataframe$Stimulus[i-1,4]

如果是这样,我将值“OK”添加到新列,但仅针对前 2 行,然后我将在第 5 列(状态)中添加值“POST”,直到第 4 列(刺激)的值变为零。

我要创建的第 5 列也可以是单独的一列数据框,其行数与原始数据框相同。没关系,我可以将它 cbind 在 and 到原始数据帧。

我的(理论上的)方法好吗?有没有更简单的方法来实现这一点?

【问题讨论】:

    标签: r


    【解决方案1】:

    首先,创建新列(dat 是数据集的名称):

    Status <- ave(dat[ , "Stimulus"], c(0, cumsum(abs(diff(dat[ , "Stimulus"])))),
                  FUN = function(x)
                          if(!x[1]) "PRE" else c(rep("OK", min(2, length(x))),
                                                 rep("POST", length(x) - 2)))
    

    现在,合并两个对象:

    cbind(dat, Status)
    

    结果:

          ID    V1     V2 Stimulus Status
    [1,]   1 74.80  803.0        0    PRE
    [2,]   1 75.98  790.9        0    PRE
    [3,]   1 75.95  791.1        0    PRE
    [4,]   1 65.70  918.7        0    PRE
    [5,]   1 59.63 1005.6       13     OK
    [6,]   1 59.44 1012.0       13     OK
    [7,]   1 59.62 1010.0       13   POST
    [8,]   1 63.85  942.4       13   POST
    [9,]   1 60.75  992.9        0    PRE
    [10,]  1 59.62 1010.0        0    PRE
    [11,]  1 61.68  974.0        0    PRE
    [12,]  1 65.21  921.4       15     OK
    [13,]  1 59.23 1012.0       15     OK
    [14,]  1 61.23  979.5       15   POST
    [15,]  1 70.80  849.2        0    PRE
    

    【讨论】:

    • 非常感谢,效果很好!如果我想显示一个从 1 开始的渐进数字(例如 1,2,3 ...)直到我遇到另一个 0,而不是 OK 和 POST,我会在 else 语句中添加什么?我尝试使用 [code]else rep(rownames(dat), length(x)))[/code] 它可以工作,但它给了我很多警告(在split&lt;-.default(*tmp*, g, value = lapply(split( x, ... : 要替换的项目数不是替换长度的倍数)
    • @Albz 您可以将else 语句替换为seq(x)。这将生成一个从 1 到长度为 x 的序列。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-24
    • 1970-01-01
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多