R:在数据框中插入多行(可变编号)
R: Insert multiple rows (variable number) in data frame
我有一个数据框,比如说,有 5 行,用于 2 个可观察值。我需要在数据框中插入 "dummy" 或 "zero" 行,以便每个 observable 的行数相同(对于更长的行,可以大于 N 行)。例如:
# 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
在每个可观察对象的原始数据框中获取 N 行,这样我就知道我需要为每个可观察对象添加多少行。
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 -
我确实实现了我的目标,但是在相当多的操作和转换中。
所以,问题 - 是否有一种更简单、更快速的方法可以在 多个 位置插入 任意 行的 empty/dummy 行在任何数据框中。列数和行数可以是任意的。
注意:上面的代码有效,所以我相信这个问题不是 "review my code" 类型,而是真正的 - "how to do it better" 问题。谢谢!
您可以尝试使用 "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)
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
如果你需要,如果你有像这样>=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
我有一个数据框,比如说,有 5 行,用于 2 个可观察值。我需要在数据框中插入 "dummy" 或 "zero" 行,以便每个 observable 的行数相同(对于更长的行,可以大于 N 行)。例如:
# 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
在每个可观察对象的原始数据框中获取 N 行,这样我就知道我需要为每个可观察对象添加多少行。
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 -
我确实实现了我的目标,但是在相当多的操作和转换中。
所以,问题 - 是否有一种更简单、更快速的方法可以在 多个 位置插入 任意 行的 empty/dummy 行在任何数据框中。列数和行数可以是任意的。
注意:上面的代码有效,所以我相信这个问题不是 "review my code" 类型,而是真正的 - "how to do it better" 问题。谢谢!
您可以尝试使用 "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)
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
如果你需要,如果你有像这样>=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