2016-08-09 176 views
0

I 2 verschiedene Datenrahmen folgendes Format haben:R - interactive subsetting von Zeilen durch den Vektor von Spaltenüberschriften

DF1 -

v1 v2 v3 v4 v5 
a 1 2 + 
b 5 2 + + 
c 5 2 +  + 
d 4 3  + + 
e 1 5 +  + 
f 3 5 
g 4 2 
h 3 1 
i 5 5 +  + 

DF2 -

v1 v2 v3 v4 
a 1 2 + 
b 5 2 + + 
c 5 2 +  
d 4 3  + 
e 1 5 +  
f 3 5 
g 4 2 
h 3 1 
i 5 5 +  

Mein Skript gibt ein Streudiagramm von v1 & v2, aber zuerst entferne ich Zeilen, die haben mindestens ein "+" in v3-v4 oder v3-v5.

Meine Datenrahmen können größer sein mit mehr v1-v2-Paaren, aber haben immer entweder die v3-v4 oder v3-v5 Spalten mit "+". Ich passe den Code manuell an, um die zu plottenden Spalten und die zu entfernenden Zeilen anzugeben, abhängig vom DF-Format, an dem ich gerade arbeite.

Es funktioniert gut, aber ich wollte das Skript interaktiv machen, wie folgt:

# Select v3-v4 or v3-v5 via interactive gui to give vector of column headers. 
remove.vars.vector <- select.list(names(DF), # Select columns as vector of column header names via interactive gui. 
          multiple = TRUE, # Can choose multiple columns. 
          title = "Choose variables to remove from data set", # Title on gui. 
          graphics = TRUE) # Allow launch of gui. 

# Return columns from DF with this vector of column headers. 
remove.vars.subset <- DF[remove.vars.vector] 
# Return rows that have at least one "+" in v3-v4 or v3-v5. 
remove.vars.subset.+ <- subset(DF, remove.vars.subset == "+") 
# Removes all rows that contain >=1 NA. 
complete.data.+ <- remove.vars.subset.+[complete.cases(remove.vars.subset.+), ] 
# Combine by rows "complete.data.+" with DF. 
combo.list <- rbind(DF,complete.data.+) 
# Remove duplicate rows from combined data frame. 
complete.data <- combo.list[!duplicated(combo.list, fromLast = FALSE) & !duplicated(combo.list, fromLast = TRUE),] 

Problem: Der obige Code, die mindestens ein „+ enthält nicht vollständig den Datenrahmen von Zeilen Streifen "in v3-4 oder v3-5. Das Problem scheint diese Zeilen zu sein:

# Return rows that have at least one "+" in v3-v4 or v3-v5. 
    remove.vars.subset.+ <- subset(DF, remove.vars.subset == "+") 

ich auch eine Reihe von Zeilen am Ende mit nur NA erhalten daher in jeder Zelle in der nächsten Zeile Code complete.cases.

Der letzte Datenrahmen enthält daher noch einige Zeilen mit "+" in v3-4 oder v3-5.

Frage:

Gibt es eine bessere Art und Weise Zeilen in einem Datenrahmen der Teilmenge einen Vektor von Spaltenüberschriften verwenden, die „+“ in ihren Reihen enthalten?

Vielen Dank im Voraus.

BEARBEITEN - 09/08/2016 - 18:54 Ich habe gerade etwas bemerkt, dass ich nicht über meine Datenrahmen geklärt habe. Einige der Zeilen haben in v3-v4 oder v3-v5 kein "+". Dies sind die Zeilen, die ich letztendlich behalten möchte, damit ich die Streuung darstellen kann. Ich habe Datenrahmen entsprechend bearbeitet. Ich schaue nur auf Antworten, um sie zu verstehen. Ich bin noch ziemlich neu in R.

Antwort

0

Ihre Daten DF ist

> DF 
    v1 v2 v3 v4 v5 
1 1 2 +  
2 5 2 + + 
3 5 2 +  + 
4 4 3  + + 
5 1 5 +  + 

Angenommen, und ich wähle v3 und v4. Dann remove.vars.subset nach Ihrem Code ist

> remove.vars.subset 
    v3 v4 
1 + 
2 + + 
3 + 
4  + 
5 + 

und feststellen, dass remove.vars.subset == "+" wertet als

> remove.vars.subset == "+" 
     v3 v4 
[1,] TRUE FALSE 
[2,] TRUE TRUE 
[3,] TRUE FALSE 
[4,] FALSE TRUE 
[5,] TRUE FALSE 

Was subset, dann ist zu tun R zu fragen Reihen zurückzukehren, aus dem Datenrahmen, wo die Bedingung TRUE auswertet, dh:

DF[c(TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE),]

die erste und zweite Spalt verketten. Aber es gibt nur 5 Zeilen im Datenrahmen, während es im logischen Vektor 10 Elemente gibt. Da DF nur 5 Zeilen hat, werden NA s angehängt (also ist es so, als ob DF 10 Zeilen hat) und der Ausdruck wird entsprechend ausgewertet. Sie sehen also:

> subset(DF, remove.vars.subset == "+") 
    v1 v2 v3 v4 v5 
1  1 2 +   
2  5 2 + +  
3  5 2 +   + 
5  1 5 +   + 
NA NA NA <NA> <NA> <NA> 
NA.1 NA NA <NA> <NA> <NA> 

Was Sie versuchen möchten, ist

DF[!apply(remove.vars.subset, MAR=1, function(x) any(x=="+")), ] 
> DF[!apply(remove.vars.subset, MAR=1, function(x) any(x=="+")), ] 
[1] v1 v2 v3 v4 v5 
<0 rows> (or 0-length row.names) 

, die keine Zeilen zurückgibt, weil alle Zeilen (angesichts der Wahl von v3 und v4) mindestens ein „+“ in Sie. Aber angenommen, wir wählten v4 und v5:

> DF[!apply(remove.vars.subset, MAR=1, function(x) any(x=="+")), ] 
    v1 v2 v3 v4 v5 
1 1 2 + 
+0

Ich habe versucht, Ihren Vorschlag und es hat perfekt funktioniert. Sie haben richtigerweise vermutet, dass einige Zeilen kein "+" hätten (Ich habe meinen Beitrag bearbeitet, bevor ich Ihren Vorschlag ausprobiert habe). Apply Familie von Funktionen hat sich an die Spitze meiner Liste für Dinge in R zu erkunden. Vielen Dank für die schnelle Antwort. –

+0

PS: Ich verifizierte, indem ich meinen ursprünglichen Methodendatenrahmen an den mit dem Änderungsantrag erstellten Datensatz anbinde, und entfernte dann doppelte Zeilen. Antwort war Datenrahmen ohne Zeilen .... genial. Mein Gehirn nimmt langsam die R-Programmierlogik auf! –

0

ich eine Lösung, wo Sie die Spalte nicht aber alle Zeilen mit „+“ und NAs werden aus dem Datenrahmen entfernt. Ich weiß nicht, ob das hilft. Es liegt folgende Frage zugrunde: Better way to filter a data frame with dplyr using OR?

v1 <- c(1,2,3,4,5,NA) 
v2 <- c(1,2,3,4,5,NA) 
v3 <- c("","+","+","","",NA) 
v4 <- c("","+","","+","",NA) 
v5 <- c("","+","","","",NA) 

D1 <- cbind.data.frame(v1,v2,v3,v4,v5,stringsAsFactors=F) 

library(dplyr) 

remove.vars.vector <- c("v3","v4","v5") 
condition <- c("+",NA) 

D1 %>% 
    filter(rowSums(sapply(D1, FUN = "%in%", condition)) == 0) -> D1_new 

EDIT: ich eine Möglichkeit gefunden, die Spalten zu wählen, leider habe ich keine Lösung finden, die Spalten nach Zeichenvektor wählen:

D1 %>% select_(remove.vars.vector) -> D1_sub # NOT working 

D1 %>% select(v3:v5) -> D1_sub # working 
D1 %>% select(v3,v4,v5) -> D1_sub # working 
D1 %>% select_("v3","v4","v5") -> D1_sub # working 

D1 %>% 
    filter(rowSums(sapply(D1_sub, FUN = "%in%", condition)) == 0) -> D1_new 
+0

Vielen Dank für Ihren Vorschlag. Ich ging eine Weile im Kreise herum und versuchte, durch einen Vektor von Spaltenüberschriften zu unterteilen. http://stackoverflow.com/users/6455166/weihuang-wong hat den Trick gemacht –