2016-08-09 2 views
0

У меня 2 разные кадры данных в следующем формате:R - интерактивный Подменю строк с помощью вектора заголовков столбцов

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 +  

Мой скрипт дает график рассеяния v1 & v2, но сначала я удаляю строки, которые имеют по крайней мере один «+» в v3-v4 или v3-v5.

Мои кадры данных могут быть больше с большим количеством пар v1-v2, но всегда имеют столбцы v3-v4 или v3-v5 с «+». Я настраиваю код вручную, чтобы указать столбцы для построения и какие строки удалить в зависимости от формата DF, над которым я работаю.

Он работает хорошо, но я хотел сделать сценарий более интерактивным следующим образом:

# 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),] 

Проблема: Приведенный выше код не полностью раздеться фрейм данных строк, которые содержат по меньшей мере один «+ "в v3-4 или v3-5. Проблема, как представляется, эти строки:

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

Я также получить количество строк в конце только NA в каждой клетке, следовательно, complete.cases в следующей строке кода.

Последний кадр данных, тем не менее, содержит несколько строк с «+» в версиях v3-4 или v3-5.

Вопрос:

Есть ли лучший способ подмножества строк в кадре данных с использованием вектора заголовков столбцов, которые могут содержать «+» в своих рядах?

Заранее спасибо.

EDIT - 09/08/2016 - 18:54 Я только что заметил то, что я не уточнил о своих кадрах данных. Некоторые из строк не имеют «+» в v3-v4 или v3-v5. Это строки, которые я в конце концов хочу сохранить, чтобы я мог разрисовать разброс. Я отредактировал рамки данных соответственно. Я просто смотрю на ответы, чтобы попытаться их понять. Я все еще новичок в R.

ответ

0

Пусть ваши данные DF является

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

и я выбираю v3 и v4. Затем remove.vars.subset после кода, является

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

и обратите внимание, что remove.vars.subset == "+" вычисляется как

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

Что subset затем делает это попросить R вернуть строки из dataframe где условие принимает значение TRUE, т.е.:

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

конкатенации первый и второй столбцы. Но в dataframe всего 5 строк, тогда как в логическом векторе есть 10 элементов. Так как DF имеет только 5 строк, добавляются NA s (так, как будто DF имеет 10 строк), и выражение оценивается соответствующим образом. Итак, вы видите:

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

Что вы можете попробовать это

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) 

который не возвращает ни одной строки, потому что все строки (учитывая выбор v3 и v4) имеют по крайней мере один «+» в их. Но предположим, что мы выбрали v4 и v5:

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

Просто попробовал свое предложение, и оно отлично сработало. Вы правильно предположили, что в некоторых строках не будет «+» (я редактировал свой пост, прежде чем я попробовал ваше предложение). Применить семейство функций переместилось в начало моего списка для вещей, которые нужно исследовать в R. Большое спасибо за быстрый ответ. –

+0

PS: Я проверил по строкам, привязывая мой исходный кадр данных метода к тому, который был создан с вашей поправкой, а затем удалил повторяющиеся строки. Ответом был кадр данных без строк .... потрясающий. Мой мозг медленно принимает логику программирования R! –

0

У меня есть решение, в котором вы не выбрать столбец, но все строки с «+» и NAs удаляются из dataframe. Я не знаю, поможет ли это. Он основан на следующий вопрос: 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: Я нашел возможность выбрать столбцы, к сожалению, я не нашел решение, чтобы выбрать столбцы по символьного вектора:

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

Благодарим вас за предложение. Я несколько раз обходил круги, пытаясь подмножить вектор заголовков столбцов. http://stackoverflow.com/users/6455166/weihuang-wong сделал трюк –