7

我已使用以下命令将大型数据文件读入 R

data <- as.data.set(spss.system.file(paste(path, file, sep = '/')))

数据集包含不应属于的列,并且仅包含空白。此问题与 R 根据附加到 SPSS 文件 ( Source ) 的变量标签创建新变量有关。

不幸的是,我无法确定解决问题所需的选项。我已经尝试了所有的:foreign::read.spss、memisc:spss.system.file 和 Hemisc::spss.get,但没有运气。

相反,我想读取整个数据集(带有幽灵列)并手动删除不必要的变量。由于幽灵列仅包含空格,因此我想从我的 data.table 中删除唯一观察数等于 1 的所有变量。

我的数据很大,所以它们以 data.table 格式存储。我想确定一种简单的方法来检查每列中唯一观察值的数量,并删除仅包含一个唯一观察值的列。

require(data.table)

### Create a data.table
dt <- data.table(a = 1:10,
                 b = letters[1:10],
                 c = rep(1, times = 10))

### Create a comparable data.frame
df <- data.frame(dt)

### Expected result
unique(dt$a)

### Expected result
length(unique(dt$a))

但是,我希望计算大型数据文件的 obs 数量,因此不需要按名称引用每一列。我不是 eval(parse()) 的粉丝。

### I want to determine the number of unique obs in
  # each variable, for a large list of vars
lapply(names(df), function(x) {
    length(unique(df[, x]))
})

### Unexpected result
length(unique(dt[, 'a', with = F]))  # Returns 1

在我看来,问题在于

dt[, 'a', with = F]

返回类“data.table”的对象。这个对象的长度为 1 是有道理的,因为它是一个包含 1 个变量的 data.table。我们知道 data.frames 实际上只是变量列表,因此在这种情况下,列表的长度仅为 1。

这是我将如何使用 data.frame 方式补救解决方案的伪代码:

for (x in names(data)) {
  unique.obs <- length(unique(data[, x]))
  if (unique.obs == 1) {
    data[, x] <- NULL
  }
}

任何关于我如何更有效地询问 data.table 中的列的唯一观察数的任何见解都将不胜感激。或者,如果您可以建议在 data.table 中只有一个唯一观察值的情况下如何删除观察结果,那就更好了。

4

4 回答 4

9

更新:uniqueN

从 1.9.6 版本开始,该解决方案有一个内置(优化)版本,即uniqueN函数。现在这很简单:

dt[ , lapply(.SD, uniqueN)]

如果要查找每列中唯一值的数量,例如

 dt[, lapply(.SD, function(x) length(unique(x)))]
##     a  b c
## 1: 10 10 1

要使您的功能正常工作,您需要使用with=FALSEwithin [.data.table,或者简单地使用[[(也请阅读fortune(312)...)

lapply(names(df) function(x) length(unique(dt[, x, with = FALSE])))

或者

 lapply(names(df) function(x) length(unique(dt[[x]])))

将工作

一步到位

dt[,names(dt) := lapply(.SD, function(x) if(length(unique(x)) ==1) {return(NULL)} else{return(x)})]


 # or to avoid calling `.SD` 

dt[, Filter(names(dt), f = function(x) length(unique(dt[[x]]))==1) := NULL]
于 2013-04-16T02:44:35.500 回答
4

其他答案中的方法很好。另一种添加方式,只是为了好玩:

for (i in names(DT)) if (length(unique(DT[[i]]))==1) DT[,(i):=NULL]

或者如果可能有重复的列名:

for (i in ncol(DT):1) if (length(unique(DT[[i]]))==1) DT[,(i):=NULL]

注意:(i)在 LHS 上:=是使用 的值i而不是名为 的列的技巧"i"

于 2013-04-16T08:47:28.237 回答
1

这是您的核心问题的解决方案(我希望我做对了)。

require(data.table)

### Create a data.table
dt <- data.table(a = 1:10,
                 b = letters[1:10],
                 d1 = "",
                 c = rep(1, times = 10),
                 d2 = "")
dt
     a b d1 c d2
 1:  1 a    1   
 2:  2 b    1   
 3:  3 c    1   
 4:  4 d    1   
 5:  5 e    1   
 6:  6 f    1   
 7:  7 g    1   
 8:  8 h    1   
 9:  9 i    1   
10: 10 j    1   

首先,我介绍了两列d1d2它们没有任何值。那些你想删除的,对吧?如果是这样,我只需识别这些列并选择dt.

only_space <- function(x) {
  length(unique(x))==1 && x[1]==""
}
bolCols <- apply(dt, 2, only_space)
dt[, (1:ncol(dt))[!bolCols], with=FALSE]

不知何故,我觉得你可以进一步简化它......

输出:

     a b c
 1:  1 a 1
 2:  2 b 1
 3:  3 c 1
 4:  4 d 1
 5:  5 e 1
 6:  6 f 1
 7:  7 g 1
 8:  8 h 1
 9:  9 i 1
10: 10 j 1
于 2013-04-16T02:41:15.100 回答
0

使用“dplyr”库有一个简单的方法,然后使用 select 函数如下:

图书馆(dplyr)

新数据 <- 选择(旧数据,第一个变量,第二个变量)

请注意,您可以选择任意数量的变量。

然后你会得到你想要的数据类型。

非常感谢,

法达

于 2016-03-03T23:34:19.200 回答