2013-04-16 12 views
5

Ich habe in einer großen Datendatei in R mit dem folgenden BefehlAnzahl der eindeutigen Obs durch Variable in einer Datentabelle

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

Der Datensatz enthält Spalten lesen, die nicht angehören sollen, und enthalten nur Leerzeichen. Dieses Problem hat damit zu tun, dass R neue Variablen erstellt, die auf den Variablenbezeichnungen basieren, die an die SPSS-Datei angehängt sind (Source).

Leider konnte ich nicht die Optionen ermitteln, die zur Lösung des Problems erforderlich sind. Ich habe alles ausprobiert: fremdes :: read.spss, muisc: spss.system.file und Hemisc :: spss.get, ohne Glück.

Stattdessen möchte ich den gesamten Datensatz (mit Geisterspalten) einlesen und unnötige Variablen manuell entfernen. Da die Geisterspalten nur Leerzeichen enthalten, möchte ich alle Variablen aus meiner data.table entfernen, in der die Anzahl der eindeutigen Beobachtungen gleich eins ist.

Meine Daten sind groß, daher werden sie im data.table-Format gespeichert. Ich möchte einen einfachen Weg finden, um die Anzahl der eindeutigen Beobachtungen in jeder Spalte zu überprüfen und Spalten zu löschen, die nur eine einzige Beobachtung enthalten.

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)) 

Ich möchte jedoch die Anzahl der obs für eine große Datendatei berechnen, so dass jede Spalte mit Namen Referenzierung nicht erwünscht ist. Ich bin kein Fan von 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 

Es ist für mich das Problem scheint, dass

dt[, 'a', with = F] 

ein Objekt der Klasse gibt "data.table". Es macht Sinn, dass die Länge dieses Objekts 1 ist, da es sich um eine data.table handelt, die 1 Variable enthält. Wir wissen, dass data.frames wirklich nur Listen von Variablen sind, und in diesem Fall ist die Länge der Liste nur 1.

Hier ist Pseudocode für, wie ich die Lösung beheben würde, mit dem data.frame Weg:

Jeder Einblick, wie ich effizienter nach der Anzahl der eindeutigen Beobachtungen nach Spalte in einer data.table fragen könnte, wäre sehr willkommen. Alternativ können Sie empfehlen, Beobachtungen zu löschen, wenn nur eine einzige Beobachtung in einer data.table vorhanden ist.

Antwort

7

Update: uniqueN

Ab Version 1.9.6, gibt es eine eingebaute (optimierte) Version dieser Lösung, die uniqueN Funktion. Nun ist dies so einfach wie:

dt[ , lapply(.SD, uniqueN)] 

Wenn Sie die Anzahl der eindeutigen Werte in jeder Spalte, so etwas wie

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

Um Ihre Funktion zu finden, wollen Sie arbeiten müssen, verwenden with=FALSE innerhalb [.data.table oder einfach [[ stattdessen

lapply(names(df) function(x) length(unique(dt[, x, with = FALSE]))) 
( fortune(312) auch ... lesen)

oder

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

wird

In einem Schritt arbeiten

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 Wie gesagt, hatte ich das Gefühl, dass ich meinen Ansatz vereinfachen könnte ... aber ich würde mit Ihrer Lösung nicht haben kommen. Verdammt, das ist ordentlich ... –

1

Hier ist eine Lösung für Ihr Kernproblem (ich hoffe, ich habe es richtig gemacht).

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 

Zuerst stelle ich zwei Spalten d1 und d2, die überhaupt keine Werte haben. Diejenigen, die Sie löschen möchten, oder? Wenn ja, identifiziere ich nur diese Spalten und wähle alle anderen Spalten in der dt.

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

Irgendwie habe ich das Gefühl, dass Sie es weiter vereinfachen könnte ...

Ausgang:

 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

Die Ansätze in den anderen Antworten sind gut. Ein anderer Weg, um die Mischung hinzufügen, nur so zum Spaß:

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

oder wenn es doppelte Spaltennamen sein kann:

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

NB: (i) auf der linke Seite von := ist ein Trick, um den Wert zu verwenden von i anstelle einer Spalte mit dem Namen "i".

0

Es gibt eine einfache Art und Weise zu tun, dass die Verwendung von "dplyr" Bibliothek und dann wählen Sie die Funktion wie folgt verwendet werden:

Bibliothek (dplyr)

newdata < - wählen (old_data, erster Variable, die zweite Variable)

Beachten Sie, dass Sie beliebig viele Variablen auswählen können.

Dann erhalten Sie die Art der Daten, die Sie wollen.

Vielen Dank,

Fadhah