我想在列总和不为零的数据框中选择变量或对其进行子集设置,同时还要保留其他因子变量。它应该很简单,但是我无法弄清楚如何使用select_if()
在变量子集上运行dplyr
函数:
df <- data.frame(
A = c("a", "a", "b", "c", "c", "d"),
B = c(0, 0, 0, 0, 0, 0),
C = c(3, 0, 0, 1, 1, 2),
D = c(0, 3, 2, 1, 4, 5)
)
require(dplyr)
df %>%
select_if(funs(sum(.) > 0))
#Error in Summary.factor(c(1L, 1L, 2L, 3L, 3L, 4L), na.rm = FALSE) :
# ‘sum’ not meaningful for factors
然后我尝试仅选择B, C, D
可行,但我没有变量A
:
df %>%
select(-A) %>%
select_if(funs(sum(.) > 0)) -> df2
df2
# C D
#1 3 0
#2 0 3
#3 0 2
#4 1 1
#5 1 4
#6 2 5
我可以简单地cbind(A = df$A, df2)
做,但由于我有一个数据集3000行和200列,恐怕这会引入错误(例如,如果值的排序方式不同)。
尝试在B, C, D
函数中对变量sum()
进行子集化无法正常工作要么:
df %>%
select_if(funs(sum(names(.[2:4])) > 0))
#data frame with 0 columns and 6 rows
答案 0 :(得分:6)
尝试一下:
df %>% select_if(~ !is.numeric(.) || sum(.) != 0)
# A C D
# 1 a 3 0
# 2 a 0 3
# 3 b 0 2
# 4 c 1 1
# 5 c 1 4
# 6 d 2 5
基本原理是,对于||
,如果左侧为TRUE
,则不会评估右侧。
注意:
select_if
的第二个参数应该是函数名称或公式(lambda函数)。必须使用~
来告诉select_if
!is.numeric(.) || sum(.) != 0
应该转换为函数。is.factor(.)
列,则应使用factor
。编辑:基本的R解决方案
cols <- c('B', 'C', 'D')
cols.to.keep <- cols[colSums(df[cols]) != 0]
df[!names(df) %in% cols || names(df) %in% cols.to.keep]
答案 1 :(得分:3)
以下更新适用于所有想要使用没有作用域变体的新 dplyr 1.0.0
(例如 select_if
,@mt1022 很好地展示了但已弃用):
df %>%
select(where(is.numeric)) %>%
select(where(~sum(.) != 0))
如果您想将两个 select 语句压缩为一个,则不能通过按元素的 &
而是通过更长的形式 &&
来执行此操作,因为这会产生所需的布尔输出:
df %>% select(where(~ is.numeric(.x) && sum(.x) !=0 ))
答案 2 :(得分:1)
这是使用data.table的解决方案
df<-data.table(
A = c("a", "a", "b", "c", "c", "d"),
B = c(0, 0, 0, 0, 0, 0),
C = c(3, 0, 0, 1, 1, 2),
D = c(0, 3, 2, 1, 4, 5)
)
df2<-df[,lapply(X = .SD,FUN = function(x){sum(as.numeric(x))}),.SDcols = colnames(df)]
df[,which(is.na(df[1,]) == F),with = F]