我想跟踪lapply
处理data.table
中列的方式。我通常在读取大量文件时这样做,但我在想是否也可以为列操作执行此操作。具体来说,假设我想使用NA
方法替换locf()
,并希望在处理每个变量时查看状态。
我注意到data.table
首先打印计数器的输出然后开始处理。
这是测试代码:
n <- 100000
reps <- 20
n1 <- 20
df <- data.table::as.data.table(as.data.frame(cbind(matrix(seq_len(n*n1), ncol=n1),
matrix(sample(0:1, n*reps, replace=TRUE), ncol=reps))))
#Randomly insert NAs
df <- data.table::as.data.table(lapply(df, function(cc)
cc[sample(c(TRUE, NA), prob = c(0.85, 0.15), size = length(cc), replace = TRUE) ]))
df$V1 <- c(1:n)
data.table::setDT(df)
counter <- 0
cols <- colnames(df)
df[, (cols):=lapply(.SD, function(x) {
counter <<- counter + 1
y <- na.locf(x, fromLast = TRUE, na.rm=FALSE)
if(counter %in% round(seq(from = 0, to = length(cols), length.out=35))) {
print(paste(round(counter/length(cols)*100,digits = 2),
"% has been processed;", counter, "columns"))
}
y
}), by = V1, .SDcols = cols]
(我在create a dataframe with random numbers中从akrun的回复中窃取了随机数据帧生成。)
以下是执行代码时发生的情况:
R首先打印:
[1] "2.5 % has been processed; 1 columns"
[1] "5 % has been processed; 2 columns"
[1] "10 % has been processed; 4 columns"
[1] "12.5 % has been processed; 5 columns"
[1] "15 % has been processed; 6 columns"
...
[1] "97.5 % has been processed; 39 columns"
[1] "100 % has been processed; 40 columns"
然后它开始处理,这是违反直觉的。有没有办法在处理列时跟踪列?
答案 0 :(得分:1)
我认为这个问题是由逐行分组引起的。
这对我有用:
library(data.table)
counter <- 0
df[, (cols) := lapply(.SD, function(x) {
counter <<- counter + 1
cat(counter, " ", length(x), " ")
cat(sum(is.na(x)), " ")
y <- zoo::na.locf(x, fromLast = TRUE, na.rm = FALSE)
cat(sum(is.na(y)), "\n")
return(y)
}), .SDcols = cols]
#1 14967 1
#2 14911 0
#3 14740 0
#...
#38 14928 0
#39 15090 1
#40 14811 0
请注意,我已删除by = V1
,因为逐行处理速度非常慢。您的by = V1
版本仅用于1000(!)行需要2.41秒,而没有行式by
的版本在100 000行中占用0.44。这是加速大约600次。
顺便说一句:na.locf()
在按行分组的情况下无法按预期工作。
为了确保在计算期间 打印,我在调用counter
之前和之后打印了NA
个元素的数量
在回复this comment by the OP和my reply后,我修改了第一个na.locf()
语句以打印cat()
的长度,以展示关键效果行分组x
。