通过R中的级别总和删除data.frame中的列

时间:2018-05-23 14:07:48

标签: r subset

这个问题很烦人,因为我整个上午都在寻找答案,而且我知道答案必须非常简单。

我有一个包含多个因子或变量的df(比本例中更多)并且只有两个级别:

row.name  Factor1 Factor2 Factor3 Factor4
1         dog     dog     cat     cat
2         dog     dog     cat     dog
3         dog     cat     dog     dog
4         dog     cat     dog     dog

现在,我只想删除包含 dog cat >的这些列。 1

row.name  Factor2 Factor3
1         dog     cat
2         dog     cat
3         cat     dog
4         cat     dog

这一定非常简单,但我无法找到合适的解决方案。我已经可以删除只包含一个级别的列,但不能删除那些包含两个级别但只有一个级别的列的列。

非常感谢任何帮助。

*修改

Ryan的两种方法在稍微改变之后都为我工作。原始解决方案仅保留仅包含的列,例如因子1

row.name  Factor1
1         dog
2         dog
3         dog
4         dog

因此,我以这种方式改变了它:

df %>% 
  select_if(~ !is.factor(.x) | sum(tabulate(.x) > 1) >= 2)

df[, sapply(df, function(x) !is.factor(x) | sum(tabulate(x) > 1) >= 2)]

两种方式都很完美。

2 个答案:

答案 0 :(得分:2)

我们可以遍历列,得到table,然后检查两个频率是否都大于2

i1 <- colSums(sapply(df1[-1], function(x) 
       table(factor(x, levels = c("cat", "dog"))))>1) <=1

df1[c(TRUE, i1)]
#  row.name Factor1 Factor4
#1        1     dog     cat
#2        2     dog     dog
#3        3     dog     dog
#4        4     dog     dog

注意:在这里,我们假设row.name是一列,因此从比较中删除了第一列(df1[-1]),并在进行子集化时与TRUE连接

答案 1 :(得分:1)

这使用tabulate而不是table,这应该更快

library(dplyr)

df %>% 
  select_if(~ !is.factor(.x) | sum(tabulate(.x) > 1) <= 1)

#   row.name Factor1 Factor4
# 1        1     dog     cat
# 2        2     dog     dog
# 3        3     dog     dog
# 4        4     dog     dog

或者,没有dplyr(相同的结果)

df[, sapply(df, function(x) !is.factor(x) | sum(tabulate(x) > 1) <= 1)]

这将选择所有非因子列,以及具有1个或更少级别的因子列,这些列出现多次。