根据R中的条件删除数据框的列
Remove columns of dataframe based on conditions in R
我必须删除我的数据框中的列,它有超过 4000 列和 180 个 rows.The 我想设置以删除数据框中的列的条件是:
(i) 如果该列中的 values/entries 少于两个,则删除该列
(ii) 如果没有两个连续的(一个接一个)删除该列
列中的值。
(iii) 删除所有值为 NA 的列。
我已经提供了删除列的条件。这里的目的不仅仅是像 "How do you delete a column in data.table?" 中那样通过名称查找列。
我说明如下:
A B C D E
0.018 NA NA NA NA
0.017 NA NA NA NA
0.019 NA NA NA NA
0.018 0.034 NA NA NA
0.018 NA NA NA NA
0.015 NA NA NA 0.037
0.016 NA NA NA 0.031
0.019 NA 0.4 NA 0.025
0.016 0.03 NA NA 0.035
0.018 NA NA NA 0.035
0.017 NA NA NA 0.043
0.023 NA NA NA 0.040
0.022 NA NA NA 0.042
所需的数据帧:
A E
0.018 NA
0.017 NA
0.019 NA
0.018 NA
0.018 NA
0.015 0.037
0.016 0.031
0.019 0.025
0.016 0.035
0.018 0.035
0.017 0.043
0.023 0.040
0.022 0.042
如何将这三个条件合并到一个代码中。非常感谢您在这方面的帮助。
可重现的例子
structure(list(Month = c("Jan-2000", "Feb-2000", "Mar-2000",
"Apr-2000", "May-2000", "Jun-2000"), A.G.L.SJ.INVS...LON..DEAD...13.08.15 = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), ABACUS.GROUP.DEAD...18.02.09 = c(0.00829384766220866,
0.00332213653674028, 0, 0, NA, NA), ABB.R..IRS. = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_)), .Names = c("Month",
"A.G.L.SJ.INVS...LON..DEAD...13.08.15", "ABACUS.GROUP.DEAD...18.02.09",
"ABB.R..IRS."), class = c("data.table", "data.frame"), row.names = c(NA,
-6L), .internal.selfref = <pointer: 0x0000000001c90788>)
为每个条件创建逻辑向量:
# condition 1
cond1 <- sapply(df, function(col) sum(!is.na(col)) < 2)
# condition 2
cond2 <- sapply(df, function(col) !any(diff(which(!is.na(col))) == 1))
# condition 3
cond3 <- sapply(df, function(col) all(is.na(col)))
然后将它们组合成一个面具:
mask <- !(cond1 | cond2 | cond3)
> df[,mask,drop=F]
A E
1 0.018 NA
2 0.017 NA
3 0.019 NA
4 0.018 NA
5 0.018 NA
6 0.015 0.037
7 0.016 0.031
8 0.019 0.025
9 0.016 0.035
10 0.018 0.035
11 0.017 0.043
12 0.023 0.040
13 0.022 0.042
感觉就这些了over-complicated。条件 2 已经包含了所有其他条件,就好像一列中至少有两个非 NA
值,显然整列都不是 NA
。而如果一列中至少有两个连续的值,那么显然这一列包含的值不止一个。因此,而不是 3 个条件,这全部总结为一个条件(我不喜欢每列 运行 许多函数,而是在每列 运行 宁 diff
之后 - vecotriize 整个事情) :
cond <- colSums(is.na(sapply(df, diff))) < nrow(df) - 1
这是可行的,因为如果一列中没有连续的值,则整列将变为 NA
s。
那么,就
df[, cond, drop = FALSE]
# A E
# 1 0.018 NA
# 2 0.017 NA
# 3 0.019 NA
# 4 0.018 NA
# 5 0.018 NA
# 6 0.015 0.037
# 7 0.016 0.031
# 8 0.019 0.025
# 9 0.016 0.035
# 10 0.018 0.035
# 11 0.017 0.043
# 12 0.023 0.040
# 13 0.022 0.042
根据您的编辑,您似乎有一个 data.table
对象并且还有一个 Date
列,因此代码需要进行一些修改。
cond <- df[, lapply(.SD, function(x) sum(is.na(diff(x)))) < .N - 1, .SDcols = -1]
df[, c(TRUE, cond), with = FALSE]
一些解释:
- 我们想忽略计算中的第一列,因此我们在对
.SD
进行操作时指定 .SDcols = -1
(这意味着 Sub D数据在data.table
是)
.N
只是行数(类似于 nrow(df)
- 下一步是按条件进行子集化。我们也不要忘记获取第一列,所以我们从
c(TRUE,...
开始
- 最后,
data.table
默认情况下使用非标准评估,因此,如果您想 select 列就像在 data.frame
中一样,您需要指定 with = FALSE
不过,更好的方法是使用 := NULL
通过引用删除该列
cond <- c(FALSE, df[, lapply(.SD, function(x) sum(is.na(diff(x)))) == .N - 1, .SDcols = -1])
df[, which(cond) := NULL]
我必须删除我的数据框中的列,它有超过 4000 列和 180 个 rows.The 我想设置以删除数据框中的列的条件是: (i) 如果该列中的 values/entries 少于两个,则删除该列 (ii) 如果没有两个连续的(一个接一个)删除该列 列中的值。 (iii) 删除所有值为 NA 的列。 我已经提供了删除列的条件。这里的目的不仅仅是像 "How do you delete a column in data.table?" 中那样通过名称查找列。 我说明如下:
A B C D E
0.018 NA NA NA NA
0.017 NA NA NA NA
0.019 NA NA NA NA
0.018 0.034 NA NA NA
0.018 NA NA NA NA
0.015 NA NA NA 0.037
0.016 NA NA NA 0.031
0.019 NA 0.4 NA 0.025
0.016 0.03 NA NA 0.035
0.018 NA NA NA 0.035
0.017 NA NA NA 0.043
0.023 NA NA NA 0.040
0.022 NA NA NA 0.042
所需的数据帧:
A E
0.018 NA
0.017 NA
0.019 NA
0.018 NA
0.018 NA
0.015 0.037
0.016 0.031
0.019 0.025
0.016 0.035
0.018 0.035
0.017 0.043
0.023 0.040
0.022 0.042
如何将这三个条件合并到一个代码中。非常感谢您在这方面的帮助。 可重现的例子
structure(list(Month = c("Jan-2000", "Feb-2000", "Mar-2000",
"Apr-2000", "May-2000", "Jun-2000"), A.G.L.SJ.INVS...LON..DEAD...13.08.15 = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), ABACUS.GROUP.DEAD...18.02.09 = c(0.00829384766220866,
0.00332213653674028, 0, 0, NA, NA), ABB.R..IRS. = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_)), .Names = c("Month",
"A.G.L.SJ.INVS...LON..DEAD...13.08.15", "ABACUS.GROUP.DEAD...18.02.09",
"ABB.R..IRS."), class = c("data.table", "data.frame"), row.names = c(NA,
-6L), .internal.selfref = <pointer: 0x0000000001c90788>)
为每个条件创建逻辑向量:
# condition 1
cond1 <- sapply(df, function(col) sum(!is.na(col)) < 2)
# condition 2
cond2 <- sapply(df, function(col) !any(diff(which(!is.na(col))) == 1))
# condition 3
cond3 <- sapply(df, function(col) all(is.na(col)))
然后将它们组合成一个面具:
mask <- !(cond1 | cond2 | cond3)
> df[,mask,drop=F]
A E
1 0.018 NA
2 0.017 NA
3 0.019 NA
4 0.018 NA
5 0.018 NA
6 0.015 0.037
7 0.016 0.031
8 0.019 0.025
9 0.016 0.035
10 0.018 0.035
11 0.017 0.043
12 0.023 0.040
13 0.022 0.042
感觉就这些了over-complicated。条件 2 已经包含了所有其他条件,就好像一列中至少有两个非 NA
值,显然整列都不是 NA
。而如果一列中至少有两个连续的值,那么显然这一列包含的值不止一个。因此,而不是 3 个条件,这全部总结为一个条件(我不喜欢每列 运行 许多函数,而是在每列 运行 宁 diff
之后 - vecotriize 整个事情) :
cond <- colSums(is.na(sapply(df, diff))) < nrow(df) - 1
这是可行的,因为如果一列中没有连续的值,则整列将变为 NA
s。
那么,就
df[, cond, drop = FALSE]
# A E
# 1 0.018 NA
# 2 0.017 NA
# 3 0.019 NA
# 4 0.018 NA
# 5 0.018 NA
# 6 0.015 0.037
# 7 0.016 0.031
# 8 0.019 0.025
# 9 0.016 0.035
# 10 0.018 0.035
# 11 0.017 0.043
# 12 0.023 0.040
# 13 0.022 0.042
根据您的编辑,您似乎有一个 data.table
对象并且还有一个 Date
列,因此代码需要进行一些修改。
cond <- df[, lapply(.SD, function(x) sum(is.na(diff(x)))) < .N - 1, .SDcols = -1]
df[, c(TRUE, cond), with = FALSE]
一些解释:
- 我们想忽略计算中的第一列,因此我们在对
.SD
进行操作时指定.SDcols = -1
(这意味着 Sub D数据在data.table
是) .N
只是行数(类似于nrow(df)
- 下一步是按条件进行子集化。我们也不要忘记获取第一列,所以我们从
c(TRUE,...
开始
- 最后,
data.table
默认情况下使用非标准评估,因此,如果您想 select 列就像在data.frame
中一样,您需要指定with = FALSE
不过,更好的方法是使用 := NULL
cond <- c(FALSE, df[, lapply(.SD, function(x) sum(is.na(diff(x)))) == .N - 1, .SDcols = -1])
df[, which(cond) := NULL]