R:在数据框中插入多行(可变数字)

时间:2015-07-02 03:41:35

标签: r dataframe transformation

我有一个数据框,例如5行,用于2个可观察对象。我需要插入" dummy"或"零"数据框中的行,以便每个可观察的行数相同(并且对于更长的行,可以大于N行)。 E.g:

#   This is what I have:
x = c("a","a","b","b","b")
y = c(2,4,5,2,6)
dft = data.frame(x,y)
print(dft)

  x y
1 a 2
2 a 4
3 b 5
4 b 2
5 b 6

以下是我想要获得的内容,即每个可观察对象添加N行为4.模拟df

x1 = c("a","a","a","a","b","b","b","b")
y1 = c(2,4,0,0,5,2,6,0)
dft1 = data.frame(x1,y1)
print(dft1)

  x1 y1
1  a  2
2  a  4
3  a  0
4  a  0
5  b  5
6  b  2
7  b  6
8  b  0

我开始使用ddply为每个observable获取原始数据框中的N行,这样我就知道需要为每个observable添加多少行。

library(plyr)
nr = ddply(dft,.(x),summarise,val=length(x))
print(nr)

  x val
1 a   2
2 b   3 

# N extras will be 2 and 1 to reach 4 per obs. 

repl      = 4 - nr$val
repl_name = nr$x
repl_x    = rep(repl_name,repl)

print(repl_x)

[1] a a b
Levels: a b

dfa = matrix("-",nrow=sum(repl),ncol=1)
dff = data.frame(repl_x,as.data.frame(dfa))

names(dff) <- names(dft)
dft = rbind(dft,dff)
dft = dft[order(as.character(dft$x)),]

print(dft)

  x y
1 a 2
2 a 4
6 a -
7 a -
3 b 5
4 b 2
5 b 6
8 b -

我确实实现了我的目标,但是在很多操作和转换中。

所以,问题是 - 在任何数据框中的几个位置插入任意数量的空/虚拟行是否有更简单,更快捷的方法。列数和行数可以是任意数。

注意:上面的代码有效,所以我相信这个问题不是&#34;检查我的代码&#34;类型,但真正的 - &#34;如何做得更好&#34;题。谢谢!

2 个答案:

答案 0 :(得分:5)

您可以尝试使用“data.table”软件包,以便使用"length<-"扩展您的行。

演示:

library(data.table)
as.data.table(dft)[, lapply(.SD, `length<-`, 4), by = x]
##    x  y  z
## 1: a  2  2
## 2: a  4  3
## 3: a NA NA
## 4: a NA NA
## 5: b  5  4
## 6: b  2  5
## 7: b  6  6
## 8: b NA NA

更新

经过Thela-the-taunter™的挑衅,如果你想坚持使用基础R,也许你可以创建如下的函数:

naRowsByGroup <- function(indf, group, rowsneeded) {
  do.call(rbind, lapply(split(indf, indf[[group]]), function(x) {
    x <- data.frame(lapply(x, `length<-`, rowsneeded))
    x[group] <- x[[group]][1]
    x
  }))
}

然后用法:

naRowsByGroup(dft, 1, 4)
#   x  y  z
# 1 a  2  2
# 2 a  4  3
# 3 a NA NA
# 4 a NA NA
# 5 b  5  4
# 6 b  2  5
# 7 b  6  6
# 8 b NA NA

示例数据:

x = c("a","a","b","b","b")
y = c(2,4,5,2,6)
z = c(2,3,4,5,6)
dft = data.frame(x,y,z)

答案 1 :(得分:2)

dft = data.frame(x=c("a","a","b","b","b"),
                 y=c(2,4,5,2,6))

x <- 4 - table(dft$x)
dd <- rbind(dft, data.frame(x = rep(names(x), x), y = NA))
dd[order(dd$x), ]

#   x  y
# 1 a  2
# 2 a  4
# 6 a NA
# 7 a NA
# 3 b  5
# 4 b  2
# 5 b  6
# 8 b NA

如果你需要,也许你可以添加一些东西,如果你有&gt; = 4行的变量已经像这样

dft =data.frame(x=c("a","a","b","b","b",rep('c',6)), y=1)
x <- 4 - table(dft$x)
x[x < 0] <- 0
dd <- rbind(dft, data.frame(x = rep(names(x), x), y = NA))
dd[order(dd$x), ]

#    x  y
# 1  a  1
# 2  a  1
# 12 a NA
# 13 a NA
# 3  b  1
# 4  b  1
# 5  b  1
# 14 b NA
# 6  c  1
# 7  c  1
# 8  c  1
# 9  c  1
# 10 c  1
# 11 c  1

对于任意数量的列:

dft = data.frame(x=c("a","a","b","b","b"),
                 y=c(2,4,5,2,6),
                 z=1,
                 zz=2)

x <- 4 - table(dft$x)
dd <- dft[1:sum(x), ]
dd[, names(dft)] <- NA
dd$x <- rep(names(x), x)
dd <- rbind(dft, dd)
dd[order(dd$x), ]

#   x  y  z zz
# 1 a  2  1  2
# 2 a  4  1  2
# 6 a NA NA NA
# 7 a NA NA NA
# 3 b  5  1  2
# 4 b  2  1  2
# 5 b  6  1  2
# 8 b NA NA NA