2016-01-20 179 views
1

我必须删除我的数据帧中有4000列和180行的列。我想设置的条件以删除数据帧中的列: (i)删除(ii)如果列中没有两个连续的(一个接一个) 值,则移除该列(如果该列中的值不足两个值/条目) 。 (iii)删除所有值为NA的列。 我已经提供了要删除列的条件。这里的目的不仅仅在于如何在“如何删除data.table中的列”中找到其名称的列。 我举例说明如下:基于R中的条件删除数据帧的列

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 

我怎样才能在一个代码incoporate这三个条件。我很感谢你在这方面的帮助。 重复的例子,

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>) 
+0

对于(I)以除去柱:'DF [,sapply(DF,函数(x)的sum(!is.na(x))> 1)]' – jogo

+0

@Frank这里删除列是根据条件而不是名称。 – Aquarius

+0

@Aquarius在链接q中,这些也是条件。它们只是基于名称而非价值向量的条件。我不认为它本质上不同。我也认为目标链接是有帮助的,因为它显示':= NULL',这是如何通过引用删除列(而不是创建一个全新的表)。 – Frank

回答

4

我觉得这一切都是过于复杂。条件2已经包括了所有其余的条件,就好像在一列中至少有两个非值,显然整列不是NAs。如果一列中至少有两个连续值,那么显然这一列包含多个值。因此,而不是3个条件,这一切都总结了成一个单一的条件(我不喜欢跑每列的许多功能,而运行diff每列〜vecotrize整个事情后):

cond <- colSums(is.na(sapply(df, diff))) < nrow(df) - 1 

这工作,因为如果有在一列中没有连续的值,整列将变为NAs。

然后,就

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] 

几点说明:

  • 我们要忽略在我们的计算中第一列,所以我们在操作时指定.SDcols = -1我们.SD(这意味着小号 UB d ATA在data.table是)
  • .N只是行数(类似于nrow(df)
  • 下一步是按条件子集。我们不必忘记抓住第一列,所以我们开始c(TRUE,...
  • 最后,data.table默认使用非标准评估,

虽然一种更好的方式,将仅仅通过参考使用:= NULL

cond <- c(FALSE, df[, lapply(.SD, function(x) sum(is.na(diff(x)))) == .N - 1, .SDcols = -1]) 
df[, which(cond) := NULL] 
+0

让我们[在聊天中继续讨论](http://chat.stackoverflow.com/rooms/101301/discussion-between-aquarius-and-david-arenburg)。 – Aquarius

4

为每个条件逻辑向量:

# 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 
+0

仅供参考,你只需要这里的条件2,它可以简化为'cond2 < - sapply(df,function(col)any(!is.na(diff(col))))'你就可以走了。所有其他条件都是多余的。 –

+2

OP对于R来说似乎是新的,所以我选择了一个更清晰,如果多余的答案,希望能够展示一种在未来可能有用的模式。虽然条件可以结合在这个例子中,但情况并非总是如此。 – Zelazny7

+0

我承担提供低效信息来执行这项任务的全部责任。我是新来的,对软件没有经验。我很抱歉,但答案2最符合我的要求。我希望你能理解。 – Aquarius