このソリューションは多少非効率的である可能性がありますが、それは主にワイドとロングとワイドの間でデータを変換するためです。ただし、「長い」形式のデータを操作する方が簡単な場合があります。
複数の行にまたがる ID があるため、最初に 2 番目の ID を生成します。
mydf$ID2 <- with(mydf, ave(ID, ID, FUN = seq_along))
次に、melt
「reshape2」パッケージから使用して、データを長い形式にします。
library(reshape2)
m.df <- melt(mydf, id.vars=c("ID", "ID2"))
長い形式のデータを使用すると、重複を特定してNA
.
m.df[duplicated(m.df[setdiff(names(m.df), "variable")]), "value"] <- NA
長い形式のデータに満足している場合。そこで止まれ。幅の広いフォームに戻したい場合は、dcast
(再び「reshape2」から) を使用します。
dcast(m.df, ID + ID2 ~ variable)
# ID ID2 code1 code2 code3
# 1 A 1 143 NA 144
# 2 A 2 35 453 NA
# 3 A 3 NA 35 15
# 4 B 1 46 NA 45
# 5 B 2 12 43 765
# 6 C 1 255 455 344
# 7 C 2 343 NA NA
# 8 C 3 343 23 NA
参考までに、これはベース R でも実行可能ですが、構文はより不器用です (「reshape2」の同等物よりもパフォーマンスが優れている可能性がありますが)。
mydf$ID2 <- with(mydf, ave(ID, ID, FUN = seq_along))
m.df <- cbind(mydf[c("ID", "ID2")],
stack(mydf[setdiff(names(mydf), c("ID", "ID2"))]))
m.df[duplicated(m.df[setdiff(names(m.df), "ind")]), "values"] <- NA
cbind(mydf[c("ID", "ID2")], unstack(m.df, values ~ ind))
更新:可能なdata.table
解決策
data.table
データが大きいと述べているため、調査することをお勧めします。考えられる解決策の 1 つを次に示します (ただし、@Arun には共有するためのより直接的な解決策がある場合があります)。
library(data.table)
DT <- data.table(mydf)
## Creates your long data.table
temp <- DT[, list(ID2 = 1:.N, Value = unlist(.SD)), by ="ID"]
## Changes duplicates to NA and adds in the "Code" column
temp[duplicated(temp), Value := NA][, Variable := rep(names(DT)[-1],
each = nrow(DT))]
## "Reshapes" the data from long to wide
temp[, as.list(setattr(Value, 'names', Variable)), by=list(ID, ID2)]
# ID ID2 code1 code1 code1
# 1: A 1 143 NA 144
# 2: A 2 35 453 NA
# 3: A 3 NA 35 15
# 4: B 1 46 NA 45
# 5: B 2 12 43 765
# 6: C 1 255 455 344
# 7: C 2 343 NA NA
# 8: C 3 343 23 NA