簡體   English   中英

R:通過比較兩行從長到寬轉變

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM