2013-04-16 58 views
5

我已經使用下面的命令許多獨特的觀測值的變量通過在數據表

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

該數據集包含其不應當屬於列讀取一個大的數據文件轉換爲R,並且只包含空白。這個問題與R根據附加到SPSS文件的變量標籤(Source)創建新變量有關。

不幸的是,我一直無法確定解決問題所需的選項。我已經嘗試了所有:foreign :: read.spss,memisc:spss.system.file和Hemisc :: spss.get,但沒有運氣。相反,我想讀取整個數據集(使用ghost列)並手動刪除不必要的變量。由於鬼列只包含空格,因此我想從我的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內只有一個獨特的觀察結果的情況下放棄觀察,則會更好。

回答

7

更新: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=FALSE[.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] 
+0

+1正如我所說的,我有我可以簡化我的做法的感覺......但我不會拿出解決方案。該死,這很整潔... –

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 
3

在其他答案的方法是很好的。另一種方法加進來,只是爲了好玩:

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] 

NB:(i)上的:=的LHS是使用值一招的i而不是名爲"i"的列。

0

有一個簡單的方法,使用 「dplyr」 庫中,然後用select函數如下:

庫(dplyr)

newdata < - 選擇(OLD_DATA,第一個變量,第二個變量)

請注意,您可以隨意選擇多個變量。

然後你會得到你想要的數據類型。

非常感謝,

Fadhah