在数据框中特定位置添加空行。

4

我希望在数据框的特定位置添加空行。假设我们有以下数据框:

df <- data.frame(var1 = c(1,2,3,4,5,6,7,8,9),
     var2 = c(9,8,7,6,5,4,3,2,1))

我想在第1行、第3行和第5行后面添加空行(我知道在大多数情况下这不是最佳实践,最终我想在这里使用flextable创建一个表格)。这些行号保存在向量中:
rows <- c(1,3,5)

现在,我想使用for循环遍历行向量,在每一行后面使用add_row()添加一个空行:
for (i in rows) {
df <- add_row(df, .after = i)
}

问题在于,虽然第一次迭代运行得很完美,但由于数据帧显然变长,其他空行会错位。为了解决这个问题,我在每次迭代后尝试将向量加1:
for (i in rows) {
df <- add_row(df, .after = i)
rows <- rows+1
}

这段代码没有起作用。我猜测行向量只被计算了一次。有没有人有什么想法?

2个回答

4

一次性完成所有操作,无需循环。创建一系列行号,添加新行,进行排序,然后用 NA 替换重复的行号:

s <- sort(c(seq_len(nrow(df)), rows))
out <- df[s,]
out[duplicated(s),] <- NA

#    var1 var2
#1      1    9
#1.1   NA   NA
#2      2    8
#3      3    7
#3.1   NA   NA
#4      4    6
#5      5    5
#5.1   NA   NA
#6      6    4
#7      7    3
#8      8    2
#9      9    1

这将比循环或类似循环的代码更有效,即使对于中等大小的数据也是如此。
df <- df[rep(1:9,1e4),]
rows <- seq(1,9e4,100)

system.time({
s <- sort(c(seq_len(nrow(df)), rows))
out <- df[s,]
out[duplicated(s),] <- NA
})
#   user  system elapsed 
#   0.01    0.00    0.02 
 
df <- df[rep(1:9,1e4),]
rows <- seq(1,9e4,100)
 
system.time({
Reduce(function(x, y) tibble::add_row(x, .after = y), rev(rows), init = df)
})
#   user  system elapsed 
#  26.03    0.00   26.03 
 
df <- df[rep(1:9,1e4),]
rows <- seq(1,9e4,100)
 
system.time({
for (i in rev(rows)) {
  df <- tibble::add_row(df, .after = i)
}
})
#   user  system elapsed 
#  25.05    0.00   25.04 

2
你可以通过反向循环来实现你的目标:
df <- data.frame(
  var1 = c(1, 2, 3, 4, 5, 6, 7, 8, 9),
  var2 = c(9, 8, 7, 6, 5, 4, 3, 2, 1)
)
rows <- c(1, 3, 5)

for (i in rev(rows)) {
  df <- tibble::add_row(df, .after = i)
}
df
#>    var1 var2
#> 1     1    9
#> 2    NA   NA
#> 3     2    8
#> 4     3    7
#> 5    NA   NA
#> 6     4    6
#> 7     5    5
#> 8    NA   NA
#> 9     6    4
#> 10    7    3
#> 11    8    2
#> 12    9    1

我对这个基准测试有点惊讶。我认为你需要增加数据集/行数才能看到时间差异。与使用90000行数据集和900次替换时的0.02秒相比,Reduce仍然需要大约25秒的时间。 - thelatemail
@thelatemail 感谢您指出这一点。我已经想知道为什么Reduce的性能比for循环要好得多,而与您的方法相比差别很小。我已经在您的大型数据集上进行了检查,正如您所说,Reduce比您的方法慢得多,在这种情况下与for循环之间的差异不大。 - stefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接