给出
index = c(1,2,3,4,5)
codes = c("c1","c1,c2","","c3,c1","c2")
df=data.frame(index,codes)
df
index codes
1 1 c1
2 2 c1,c2
3 3
4 4 c3,c1
5 5 c2
如何创建一个看起来像
的新dfdf1
index codes
1 1 c1
2 2 c1
3 2 c2
4 3
5 4 c3
6 4 c1
7 5 c2
这样我就可以对代码进行聚合了吗?实际数据集的“索引”是一系列时间戳,因此我希望按天或小时聚合。
答案 0 :(得分:3)
如果变量索引具有唯一键,则Roland的方法非常好。您可以直接使用列表来获得一些速度。考虑到:
NA
。 所以我的想法是:
数据:
index = c(1,2,3,4,5)
codes = c("c1","c1,c2",NA,"c3,c1","c2")
df=data.frame(index,codes,stringsAsFactors=FALSE)
然后:
X <- strsplit(df$codes,",")
data.frame(
index = rep(df$index,sapply(X,length)),
codes = unlist(X)
)
或者,如果您坚持使用""
而不是NA:
X <- strsplit(df$codes,",")
ll <- sapply(X,length)
X[ll==0] <- NA
data.frame(
index = rep(df$index,pmax(1,ll)),
codes = unlist(X)
)
这两种方法都没有假定index
中的唯一键。它们非常适合非独特的时间戳。
答案 1 :(得分:1)
您需要拆分字符串(使用strsplit
),然后将结果列表与data.frame合并。
以下内容依赖于代码在每一行中都是唯一的假设。如果你在某些行中有很多代码而在其他行中只有很少的代码,这可能会浪费大量的内存并且循环可能会更好。
#to avoid character(0), which would be omitted in rbind
levels(df$codes)[levels(df$codes)==""] <- " "
#rbind fills each row by propagating the values to the "empty" columns for each row
df2 <- cbind(df, do.call(rbind,strsplit(as.character(df$codes),",")))[,-2]
library(reshape2)
df2 <- melt(df2, id="index")[-2]
#here the assumtion is needed
df2 <- df2[!duplicated(df2),]
df2[order(df2[,1], df2[,2]),]
# index value
#1 1 c1
#2 2 c1
#7 2 c2
#3 3
#9 4 c1
#4 4 c3
#5 5 c2
答案 2 :(得分:0)
这是使用“data.table”的另一种选择。示例数据包括NA
而不是空格,并包含重复的索引值:
index = c(1,2,3,2,4,5)
codes = c("c1","c1,c2",NA,"c3,c1","c2","c3")
df = data.frame(index,codes,stringsAsFactors=FALSE)
library(data.table)
## We could create the data.table directly, but I'm
## assuming you already have a data.frame ready to work with
DT <- data.table(df)
DT[, list(codes = unlist(strsplit(codes, ","))), by = "index"]
# index codes
# 1: 1 c1
# 2: 2 c1
# 3: 2 c2
# 4: 2 c3
# 5: 2 c1
# 6: 3 NA
# 7: 4 c2
# 8: 5 c3