【问题标题】:R: Fill empty cell with value of last non-empty cellR:用最后一个非空单元格的值填充空单元格
【发布时间】:2016-07-19 23:59:51
【问题描述】:

在 Excel 中,可以很容易地抓住一列中的一个单元格,然后向下拖动光标来替换下面的许多单元格,使每个单元格都变成与原来相同的值。

这个函数可以在 R 中使用 for 循环来执行。今天我花了一些时间试图弄清楚,并认为我会为了下一个人的利益而分享:

for (row in 2:length(data$column)){ # 2 so you don't affect column names
    if(data$column[row] == "") {    # if its empty...
        data$column[row] = data$column[row-1] # ...replace with previous row's value
    }
}

这对我有用,尽管运行一个巨大的数据文件需要很长时间(5-10 分钟)。也许有一种更有效的方法来实现这个功能,我鼓励任何人说出如何做到这一点。

谢谢,祝你好运。

【问题讨论】:

  • library(zoo) na.locf() 我相信更快。
  • 不是问题,所以它属于一个问题?

标签: r cell fill


【解决方案1】:
df <- data.frame(a = c(1:5, "", 3, "", "", "", 4), stringsAsFactors = FALSE)

> df
   a
1  1
2  2
3  3
4  4
5  5
6   
7  3
8   
9   
10  
11 4

while(length(ind <- which(df$a == "")) > 0){
  df$a[ind] <- df$a[ind -1]
}

> df
   a
1  1
2  2
3  3
4  4
5  5
6  5
7  3
8  3
9  3
10 3
11 4

编辑:添加时间配置文件

set.seed(1)
N = 1e6
df <- data.frame(a = sample(c("",1,2),size=N,replace=TRUE),
                 stringsAsFactors = FALSE)

if(df$a[1] == "") {df$a[1] <- NA}

system.time(
  while(length(ind <- which(df$a == "")) > 0){
    df$a[ind] <- df$a[ind - 1]
  }, gcFirst = TRUE)

user  system elapsed 
0.89    0.00    0.88 

【讨论】:

  • 您的 while 循环是一个真正漂亮的解决方案,它利用了 R 的向量化。
【解决方案2】:

这里使用来自zoo 包中的na.locf 的快速解决方案,应用在data.table 中。我在结果中创建了一个新列 y 以更好地可视化替换缺失值的效果(此处易于替换 x 列)。由于na.locf 替换了缺失值,因此需要一个额外的步骤来将所有零长度值替换为NA。该解决方案非常快,并且在我的机器中 1e6 行花费不到 半秒

library(data.table)
library(zoo)
N=1e6  ##  number of rows 
DT <- data.table(x=sample(c("",1,2),size=N,replace=TRUE))
system.time(DT[!nzchar(x),x:=NA][,y:=na.locf(x)])
## user  system elapsed 
## 0.59    0.30    1.78 
# x y
# 1:  2 2
# 2: NA 2
# 3: NA 2
# 4:  1 1
# 5:  1 1
# ---     
#   999996:  1 1
# 999997:  2 2
# 999998:  2 2
# 999999: NA 2
# 1000000: NA 2

【讨论】:

  • 一个小问题。如果数据中有实际的NA 值,这也将替换它们。以dt &lt;- data.table(x=c(1,NA,2,"","")) 为例。
  • @thelatemail 很好,即使NA"" 具有相同的缺失值精神!在进一步了解此答案之前,我会等待用户示例和预期结果。
【解决方案3】:

借用 agstudy 的 MWE:

library(dplyr)
library(zoo)

N = 1e6
df <- data.frame(x = sample(c(NA,"A","B"), size=N, replace=TRUE))

system.time(test <- df %>% dplyr::do(zoo::na.locf(.)))
   user  system elapsed 
  0.082   0.000   0.130 

【讨论】: