如何根据R中没有循环的数据框中的其他值来比较当前行和上一行的值

时间:2016-06-29 13:54:56

标签: r

我有一个日志文件转换为数据框,数据如下:

Client  Date    Group   Count   Test
C1  1.437512e+12    6   2   0
C1  1.437685e+12    3   1   0
C2  1.437685e+12    3   1   0
C2  1.437772e+12    6   1   0
C2  1.438117e+12    6   2   0
C2  1.464037e+12    3   3   0
C3  1.448662e+12    6   2   0
C3  1.451081e+12    3   5   0
C4  1.437944e+12    6   1   0
C4  1.438895e+12    3   6   0
C5  1.460581e+12    3   2   0
C5  1.460668e+12    6   2   0
C5  1.460927e+12    6   1   0
C5  1.461013e+12    3   2   0
C6  1.437685e+12    3   1   0
C6  1.437944e+12    6   1   0
C6  1.447711e+12    3   2   0
C6  1.458079e+12    3   2   0
C7  1.463000e+12    3   5   0
C7  1.463000e+12    10  1   0
C8  1.463951e+12    6   5   0
C8  1.463951e+12    3   1   0
C9  1.463346e+12    3   5   0
C9  1.464037e+12    10  1   0
C10 1.459804e+12    3   2   0
C10 1.461272e+12    3   1   0
C10 1.461877e+12    5   1   0
C10 1.462223e+12    5   1   0
C10 1.462482e+12    5   1   0

客户是数据库中人员的ID。群组是当前时刻此人的类别(行从最新到最新排序)。 Count是当天用户所做事件的计数。测试是一个我想填充值的列。

我的主要目标是为每个用户只获取那些形成此数据框的行,在其第一次更改为某个数字之前具有Group = 3,即不等于3.我想在Test列中标记这些行然后将每个用户对此行的Count值求和。

我尝试用for循环来解决这个问题:

for (i in 2:length(log$Group)){
 if (log$Client[i-1] == log$Client[i]) {
  if ((log$Group[i-1] == 3) & (log$Group[i] != 3)) {
   log$Test[i] <- NA
  }
  if ((log$Group[i-1] != 3) & (log$Group[i] == 3)) {
   log$Test[i] <- NA
  }
  if ((log$Group[i-1] == 3) & (log$Group[i] == 3)) {
   if(is.na(log$Test[i-1])) {
    log$Test[i] <- NA
   }
  }
  if ((log$Group[i-1] != 3) & (log$Group[i] != 3)) {
   log$Test[i] <- NA
   log$Test[i-1] <- NA
  }
 }
}

但是在完整数据上运行此循环需要很长时间。然后我将删除所有带有NA的行。

结果如下:

Client  Date    Group   Count   Test
C2  1.437685e+12    3   1   1
C5  1.460581e+12    3   2   1
C6  1.437685e+12    3   1   1
C7  1.463000e+12    3   5   1
C9  1.463346e+12    3   5   1
C10 1.459804e+12    3   2   1
C10 1.461272e+12    3   1   1

有没有办法在没有循环的情况下完成所有这些操作?或者可能有更好的方法来解决整个问题?

1 个答案:

答案 0 :(得分:1)

如果我理解你的问题(并且很难理解),你应该做以下的事情(使用包dplyr):

eventsToAnalyze %>%
    filter(group == 3) %>%
    group_by(client) %>%
    summarize(total = sum(Count))

这将过滤掉不在第3组中的行,并按客户端对Count列中的值进行求和。

修改

啊,既然你已经澄清了你的问题,我就看到了问题。如果3是最低值,这应该有效:

eventsToAnalyze %>%
    group_by(client) %>%
    filter(cummax(group) <= 3) %>%
    summarize(total = sum(Count))

否则你可以使用更混乱,但更通用:

eventsToAnalyze %>%
    group_by(client) %>%
    filter(cummax(abs(group - 3)) <= 0) %>%
    summarize(total = sum(Count))