R - 如果列相同,则从数据框中删除列

时间:2017-08-31 17:08:23

标签: r dataframe

我有一个数据框,有100多列和10000行。如果该列中的所有行都相同,然后将其删除,则手动检查每列中的数据将变得更加困难。

所以,我正在寻找一个函数,它将我的数据帧作为输入并输出另一个只有列不相同的数据帧。

输入数据框将类似于:

data<- read.table(text = "
A B C D
1 1 3 4
1 2 2 4", header = TRUE)

我希望输出数据框为:

B C
1 3
2 2

感谢。

3 个答案:

答案 0 :(得分:4)

一个选项是Filter,只保留其length元素unique大于1的列

Filter(function(x) length(unique(x))>1, data)
#  B C
#1 1 3
#2 2 2

或另一个选项是sapply

data[sapply(data, function(x) length(unique(x)))>1]

anyDuplicated

data[!sapply(data, anyDuplicated)]

答案 1 :(得分:4)

在这里添加一些选项:

如果所有元素都相同,则表示最小值和最大值相同。请注意,这些是高度优化的内置函数。同样,如果所有元素都相同,则方差为0.在代码中:

$ docker images | grep test-tgz
test-tgz-curl               latest                                     2776133659af        30 seconds ago      269MB
test-tgz-add                latest                                     d625455998ff        2 minutes ago       359MB

如果是性能问题,那就让我们进行比较:

df[, !sapply(df, function(x) min(x) == max(x))]
df[, !sapply(df, function(x) var(x) == 0)] # if all numeric

内置的# 100 columns and 10000 rows with duplicates: df <- data.frame( matrix(rnorm(10000*50),ncol=50), # 50 columns, non-repeating matrix(1:50, ncol=50)[rep(1,10000),] # 50 columns, identical elements ) ak <- function(){ Filter(function(x) length(unique(x))>1, df) } ak2 <- function(){ df[sapply(df, function(x) length(unique(x)))>1] } ak3 <- function(){ df[!sapply(df, anyDuplicated)] } cj <- function(){ df[, !sapply(df, function(x) var(x) == 0)] } cj2 <- function(){ df[, !sapply(df, function(x) min(x) == max(x))] } library(microbenchmark) microbenchmark(ak(), ak2(), ak3(), cj(), cj2()) Unit: milliseconds expr min lq mean median uq max neval ak() 17.472319 17.870399 19.586547 19.040228 19.762838 66.545086 100 ak2() 17.412296 18.152165 19.830981 19.127153 19.908074 65.856221 100 ak3() 11.359604 11.608405 12.475312 11.939775 12.966077 18.132573 100 cj() 6.799404 7.043694 7.466027 7.175871 7.472253 10.451793 100 cj2() 4.068508 4.237848 4.306551 4.279522 4.373600 4.901368 100 min功能据称是高度优化的,这解释了良好的性能。考虑到所涉及的许多计算(计算均值,从所有元素中减去均值,对结果求平方,求和),我几乎感到惊讶max做得很好。

答案 2 :(得分:3)

使用sapply浏览每个列。然后,为每列检查所有元素是否等于第一个元素。

data[!sapply(data, function(x) all(x == x[1]))]
#  B C
#1 1 3
#2 2 2

microbenchmark的结果如下所示。请注意,在这种情况下db()

db = function(){
    df[!sapply(df, function(x) all(x == x[1]))]
}

所有其他功能和数据均来自coffeinjunky's answer

with(microbenchmark(db(), ak(), ak2(), ak3(), cj(), cj2()),
     boxplot(x = split(time/1e6, expr), outline = FALSE, ylab = "milliseconds"))

enter image description here