[英]R: Transforming long to wide through comparing two rows
我花了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個小時左右的時間,但它卻很討厭而且很丑陋!
是否有適當代碼的想法?
非常感謝!
這是可以與該示例一起使用的基本方法:
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
這是使用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"))))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.