0

我花了 4 天时间试图解决这个问题,从其他相关问题中学到了很多东西,但仍然找不到有效的解决方案。开始:

我有一个包含 500k x 40 个变量的数据集,并且需要将一个变量从长转换为宽,以比较两个连续行之间的比较。
数据样本如下所示:

df <- data.frame(id=c(267, 268, 269, 269, 270, 271, 272, 272, 273, 274),              
           quant=c(2,1,4,4,1,5,2,2,3,1),
           pts=  c(3,2,7,11,2,4,5,9,6,4),
           kind=c('v','v', 'v', 'c', 'v', 'v', 'v', 'c', 'v','v'))

    id quant pts kind
1  267     2   3    v
2  268     1   2    v
3  269     4   7    v
4  269     4  11    c
5  270     1   2    v
6  271     5   4    v
7  272     2   5    v
8  272     2   9    c
9  273     3   6    v
10 274     1   4    v

请注意,每次id重复时,quant也是如此,并且变量kind在一行中假设值为 'v' 而在另一行中假设为 'c'。相反,'c' 的值仅出现在具有重复id的记录中。

我打算得到以下data.frame:

    id quant pts kind  c
1  267     2   3    v  0
2  268     1   2    v  0
3  269     4   7    v 11
5  270     1   2    v  0
6  271     5   4    v  0
7  272     2   5    v  9
9  273     3   6    v  0
10 274     1   4    v  0    

我已经使用以下代码弄清楚了:

df$c <- 0
df$delete <- 0
for (i in 1:(dim(df)[1] - 1)) {
  if (df[i,'id'] == df[i+1, 'id'] & df[i+1, 'kind'] == 'c')
  {
    df[i, 'c'] <- df[i+1, 'pts']
    df[i+1, 'delete'] <- 1
  }
}
df <- df[df$delete == 0, ]
df$delete <- NULL    

虽然在原始数据集中需要大约 10 个小时,但它是令人讨厌和令人讨厌的,但它确实有效!

任何正确代码的想法?
非常感谢!

4

2 回答 2

1

这是可用于此示例的基本方法:

df$c <- with(df, ave(pts, id, quant, FUN = function(x) {
  ifelse(length(x) == 1, 0, tail(x, 1))
}))
df <- df[df$kind == "v", ]
df
#     id quant pts kind  c
# 1  267     2   3    v  0
# 2  268     1   2    v  0
# 3  269     4   7    v 11
# 5  270     1   2    v  0
# 6  271     5   4    v  0
# 7  272     2   5    v  9
# 9  273     3   6    v  0
# 10 274     1   4    v  0

更新

顺便说一句,这有趣data.table

这是数据:

library(data.table)
DT <- data.table(id = c(267, 268, 269, 269, 270, 271, 272, 272, 273, 274), 
                 quant = c(2, 1, 4, 4, 1, 5, 2, 2, 3, 1),
                 pts = c(3, 2, 7, 11, 2, 4, 5, 9, 6, 4),
                 kind = c('v','v', 'v', 'c', 'v', 'v', 'v', 'c', 'v','v'),
                 key = c("id", "quant"))
DT
#      id quant pts kind
#  1: 267     2   3    v
#  2: 268     1   2    v
#  3: 269     4   7    v
#  4: 269     4  11    c
#  5: 270     1   2    v
#  6: 271     5   4    v
#  7: 272     2   5    v
#  8: 272     2   9    c
#  9: 273     3   6    v
# 10: 274     1   4    v

这就是您正在寻找的东西:

DT[, c := ifelse(length(pts) == 1, 0, tail(pts, 1)), by = key(DT)][kind == "v"]
#     id quant pts kind  c
# 1: 267     2   3    v  0
# 2: 268     1   2    v  0
# 3: 269     4   7    v 11
# 4: 270     1   2    v  0
# 5: 271     5   4    v  0
# 6: 272     2   5    v  9
# 7: 273     3   6    v  0
# 8: 274     1   4    v  0
于 2013-04-10T07:58:19.160 回答
0

这里使用包 plyr 的方法:

DF <- ddply(df, .(id), function(x) cbind(x[1,], c=x$pts[match("c", x$kind)]))
DF$c[is.na(DF$c)] <- 0
# or
DF <- ddply(df, .(id), function(x) cbind(x[1,], c=sum(x$pts*(x$kind=="c"))))
于 2013-04-10T08:08:14.900 回答