如何根据列中的值从 data.table 中删除列
How to delete columns from a data.table based on values in column
背景
我有一些财务数据(1.5 年 SP500 股票),我使用 data.table 包将其处理成宽格式。在学习了 Datacamp 上的整个 data.table 课程后,我开始掌握基础知识,但搜索了几个小时后,我不知道如何做到这一点。
问题
数据包含每只股票的财务数据列。我需要删除包含两个连续 NAs.
的列
我的猜测是我必须使用 rle()
、lapply()
来查找连续的值和 DT[,x:= NULL]
) 来删除列。
我读到 rle()
不适用于 NAs,所以我将它们改为 Inf。
我只是不知道如何组合这些功能,以便我可以有效地删除我拥有的 460 中的几列。
使用 data.table
的答案会很棒,但非常感谢任何有效的答案。
或者,我很想知道如何删除至少包含 1 个 NA 的列
示例数据
> test[1:5,1:5,with=FALSE]
date 10104 10107 10138 10145
1: 2012-07-02 0.003199 Inf 0.001112 -0.012178
2: 2012-07-03 0.005873 0.006545 0.001428 Inf
3: 2012-07-05 Inf -0.001951 -0.011090 Inf
4: 2012-07-06 Inf -0.016775 -0.009612 Inf
5: 2012-07-09 -0.002742 -0.006129 -0.001294 0.005830
> dim(test)
[1] 377 461
期望的结果
date 10107 10138
1: 2012-07-02 Inf 0.001112
2: 2012-07-03 0.006545 0.001428
3: 2012-07-05 -0.001951 -0.011090
4: 2012-07-06 -0.016775 -0.009612
5: 2012-07-09 -0.006129 -0.001294
PS。这是我的第一个问题,我已经尽力遵守规则,如果我需要更改任何内容,请告诉我。
显然问题是发现 连续 不见了。
首先,根据缺失 NA
创建一个矩阵 TRUE/FALSE
。使用该矩阵将每一行与下一行进行比较。保留原始矩阵中的列,其中 colSums == 0
试试这个:
Missing.Mat <- apply(test, 2, is.na)
Consecutive.Mat <- Missing.Mat[-nrow(Missing.Mat),] * Missing.Mat[-1,]
Keep.Cols <- colSums(Consecutive.Mat) == 0
test[,Keep.Cols]
这是我想到的。它在向量 y
上调用 rle
,即 1:length(column)
,除非该列的对应元素是 Inf
,在这种情况下,y 中的对应值为零。然后它检查是否有任何运行大于 1。
keep <- c(date = T, apply(dat[, -1], 2,
function(x) {
y <- 1:length(x)
y[!is.finite(x)] <- 0
return(!any(rle(y)$lengths > 1))
}))
dat2 <- dat[, keep]
dat2
# date X10107 X10138
# 1 2012-07-02 Inf 0.001112
# 2 2012-07-03 0.006545 0.001428
# 3 2012-07-05 -0.001951 -0.011090
# 4 2012-07-06 -0.016775 -0.009612
# 5 2012-07-09 -0.006129 -0.001294
请注意,列名前面有 "X" by read.table
。
现在,数据输出:
dat <- structure(list(date = c("2012-07-02", "2012-07-03", "2012-07-05",
"2012-07-06", "2012-07-09"), X10104 = c(0.003199, 0.005873, Inf,
Inf, -0.002742), X10107 = c(Inf, 0.006545, -0.001951, -0.016775,
-0.006129), X10138 = c(0.001112, 0.001428, -0.01109, -0.009612,
-0.001294), X10145 = c(-0.012178, Inf, Inf, Inf, 0.00583)), .Names = c("date",
"X10104", "X10107", "X10138", "X10145"), class = "data.frame", row.names = c(NA,
-5L))
要检测并删除包含至少一个 NA 的列,您可以尝试以下操作
data = data.frame(A=c(1,2,3,4,5), B=c(2,3,4,NA,6), C=c(3,4,5,6,7), D=c(4,5,NA,NA,8))
colsToDelete = lapply(data, FUN = function(x){ sum(is.na(x)) >= 1 })
data.formatted = data[,c(!unlist(colsToDelete))]
这是一个 rle
版本:
dt[, sapply(dt, function(x)
setDT(rle(is.na(x)))[, sum(lengths > 1 & values) == 0]), with = F]
如果您愿意,也可以将 is.na
替换为 is.infinite
。
背景
我有一些财务数据(1.5 年 SP500 股票),我使用 data.table 包将其处理成宽格式。在学习了 Datacamp 上的整个 data.table 课程后,我开始掌握基础知识,但搜索了几个小时后,我不知道如何做到这一点。
问题
数据包含每只股票的财务数据列。我需要删除包含两个连续 NAs.
的列我的猜测是我必须使用 rle()
、lapply()
来查找连续的值和 DT[,x:= NULL]
) 来删除列。
我读到 rle()
不适用于 NAs,所以我将它们改为 Inf。
我只是不知道如何组合这些功能,以便我可以有效地删除我拥有的 460 中的几列。
使用 data.table
的答案会很棒,但非常感谢任何有效的答案。
或者,我很想知道如何删除至少包含 1 个 NA 的列
示例数据
> test[1:5,1:5,with=FALSE]
date 10104 10107 10138 10145
1: 2012-07-02 0.003199 Inf 0.001112 -0.012178
2: 2012-07-03 0.005873 0.006545 0.001428 Inf
3: 2012-07-05 Inf -0.001951 -0.011090 Inf
4: 2012-07-06 Inf -0.016775 -0.009612 Inf
5: 2012-07-09 -0.002742 -0.006129 -0.001294 0.005830
> dim(test)
[1] 377 461
期望的结果
date 10107 10138
1: 2012-07-02 Inf 0.001112
2: 2012-07-03 0.006545 0.001428
3: 2012-07-05 -0.001951 -0.011090
4: 2012-07-06 -0.016775 -0.009612
5: 2012-07-09 -0.006129 -0.001294
PS。这是我的第一个问题,我已经尽力遵守规则,如果我需要更改任何内容,请告诉我。
显然问题是发现 连续 不见了。
首先,根据缺失 NA
创建一个矩阵 TRUE/FALSE
。使用该矩阵将每一行与下一行进行比较。保留原始矩阵中的列,其中 colSums == 0
试试这个:
Missing.Mat <- apply(test, 2, is.na)
Consecutive.Mat <- Missing.Mat[-nrow(Missing.Mat),] * Missing.Mat[-1,]
Keep.Cols <- colSums(Consecutive.Mat) == 0
test[,Keep.Cols]
这是我想到的。它在向量 y
上调用 rle
,即 1:length(column)
,除非该列的对应元素是 Inf
,在这种情况下,y 中的对应值为零。然后它检查是否有任何运行大于 1。
keep <- c(date = T, apply(dat[, -1], 2,
function(x) {
y <- 1:length(x)
y[!is.finite(x)] <- 0
return(!any(rle(y)$lengths > 1))
}))
dat2 <- dat[, keep]
dat2
# date X10107 X10138
# 1 2012-07-02 Inf 0.001112
# 2 2012-07-03 0.006545 0.001428
# 3 2012-07-05 -0.001951 -0.011090
# 4 2012-07-06 -0.016775 -0.009612
# 5 2012-07-09 -0.006129 -0.001294
请注意,列名前面有 "X" by read.table
。
现在,数据输出:
dat <- structure(list(date = c("2012-07-02", "2012-07-03", "2012-07-05",
"2012-07-06", "2012-07-09"), X10104 = c(0.003199, 0.005873, Inf,
Inf, -0.002742), X10107 = c(Inf, 0.006545, -0.001951, -0.016775,
-0.006129), X10138 = c(0.001112, 0.001428, -0.01109, -0.009612,
-0.001294), X10145 = c(-0.012178, Inf, Inf, Inf, 0.00583)), .Names = c("date",
"X10104", "X10107", "X10138", "X10145"), class = "data.frame", row.names = c(NA,
-5L))
要检测并删除包含至少一个 NA 的列,您可以尝试以下操作
data = data.frame(A=c(1,2,3,4,5), B=c(2,3,4,NA,6), C=c(3,4,5,6,7), D=c(4,5,NA,NA,8))
colsToDelete = lapply(data, FUN = function(x){ sum(is.na(x)) >= 1 })
data.formatted = data[,c(!unlist(colsToDelete))]
这是一个 rle
版本:
dt[, sapply(dt, function(x)
setDT(rle(is.na(x)))[, sum(lengths > 1 & values) == 0]), with = F]
如果您愿意,也可以将 is.na
替换为 is.infinite
。