如何根据另一行的内容在数据框中创建新行

时间:2013-12-19 14:33:40

标签: r

给出

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

如何创建一个看起来像

的新df
df1
  index codes
1     1    c1
2     2    c1
3     2    c2
4     3      
5     4    c3
6     4    c1
7     5    c2

这样我就可以对代码进行聚合了吗?实际数据集的“索引”是一系列时间戳,因此我希望按天或小时聚合。

3 个答案:

答案 0 :(得分:3)

如果变量索引具有唯一键,则Roland的方法非常好。您可以直接使用列表来获得一些速度。考虑到:

  • 在原始数据框中,代码是一个因素。没有必要这样做,你希望它成为一个角色。
  • 在原始数据框中,使用“”代替NA。由于该长度为0,您可以在以后遇到各种麻烦。我在那里使用NA。 “”是一个实际值,“”根本没有值,但你想要一个缺失值。因此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