答案 0 :(得分:2)
您需要首先创建另一个变量v1
或v2
(对于上面给出的示例数据)。
我们使用ave
和seq_along
创建游程类型id列'idx'
。此变量将从1
到每组'IDBILL'
的观测总数。我们使用paste0
添加后缀"v"
。
(DF <- transform(DF,
idx = ave(IDPRODUCT,
IDBILL, # grouping variable
FUN = function(x) paste0("v", seq_along(x))
)))
# IDBILL IDPRODUCT idx
#1 111 ABC123 v1
#2 111 ABC124 v2
#3 112 BCH134 v1
#4 113 ABC123 v1
#5 113 GDF345 v2
现在使用dcast
中的reshape2
展开'idx'
列并填写'IDPRODUCT'
的值。
library(reshape2)
(dcast(DF, IDBILL ~ idx, value.var = 'IDPRODUCT'))
# IDBILL v1 v2
#1 111 ABC123 ABC124
#2 112 BCH134 <NA>
#3 113 ABC123 GDF345
如果没有其他软件包,则可以使用reshape
代替dcast
。
reshape(DF, idvar = "IDBILL", timevar = "idx", direction = "wide")
如果您更喜欢data.table
,可以尝试
library(data.table)
setDT(DF)[, idx := paste0("v", rleid(IDPRODUCT)), by = IDBILL]
dcast(DF, IDBILL ~ idx, value.var = 'IDPRODUCT')
要最终完成邪恶的三位一体,请尝试tidyverse
library(tidyverse)
DF %>%
group_by(IDBILL) %>%
mutate(idx = paste0("v", row_number())) %>%
spread(idx, IDPRODUCT) %>%
ungroup()
数据
DF <- structure(list(IDBILL = c(111, 111, 112, 113, 113), IDPRODUCT = c("ABC123",
"ABC124", "BCH134", "ABC123", "GDF345")), .Names = c("IDBILL",
"IDPRODUCT"), row.names = c(NA, -5L), class = "data.frame")
答案 1 :(得分:0)
我希望您也考虑这种解决方案。
数据生成
dt<-data.frame("id"=sample(3,5,replace = TRUE),value=sample(5))
m<-merge(dt, dt)
然后
IDs<-unique(m[,1])
i<-1
res<-NULL
while(i<=length(IDs)){
res<-rbind(res, c(IDs[i],m[m[,1]==IDs[i],2]))
i<-i+1
}
res
您可以使用rbind
或rbind.na