2016-04-24 8 views
0

У меня есть 2 кадра данных, первый столбец одного из них - это список (df A), первый столбец другого содержит элементы из списка, но в некоторых случаях каждая строка имеет несколько элементов (df B). То, что я хочу сделать, это пройти и создавать новые строки для каждого элемента из ДФ А, что происходит в первой колонке ДФ В.Создайте новые строки фрейма данных на основе столбца из другого фрейма данных

DF

dfA 
    Index X 
1 1 alpha 
2 2 beta 
3 3 gamma 
4 4 delta 

DF B

dfB 
    list X 
1 1 4 alpha 
2 3 2 1 beta 
3 4 1 2 gamma 
4 3  delta 

Желаемая

dfC 
    Index x 
1 1  alpha 
2 4  alpha 
3 3  beta 
4 2  beta 
5 1  beta 
6 4  gamma 
7 1  gamma 
8 2  gamma 
9 3  delta 

фактические данные я использую: DF

dput(head(allwines)) 
structure(list(Wine = c("Albariño", "Aligoté", "Amarone", "Arneis", 
"Asti Spumante", "Auslese"), Description = c("Spanish white wine grape that makes crisp, refreshing, and light-bodied wines.", 
"White wine grape grown in Burgundy making medium-bodied, crisp, dry wines with spicy character.", 
"From Italy’s Veneto Region a strong, dry, long- lived red, made from a blend of partially dried red grapes.", 
"A light-bodied dry wine the Piedmont Region of Italy", "From the Piedmont Region of Italy, A semidry sparkling wine produced from the Moscato di Canelli grape in the village of Asti", 
"German white wine from grapes that are very ripe and thus high in sugar" 
)), .Names = c("Wine", "Description"), row.names = c(NA, 6L), class = "data.frame") 

DF B

> dput(head(cheesePairing)) 
structure(list(Wine = c("Cabernet Sauvignon\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Pinot Noir\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Sauvignon Blanc\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Zinfandel", 
"Chianti\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Pinot Noir\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Sangiovese", 
"Chardonnay", "Bardolino\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Malbec\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Riesling\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Rioja\r\n        \r\n       \r\n      \r\n       \r\n        \r\n         Sauvignon Blanc", 
"Tempranillo", "Asti Spumante"), Cheese = c("Abbaye De Belloc Cheese", 
"Ardrahan cheese", "Asadero cheese", "Asiago cheese", "Azeitao", 
"Baby Swiss Cheese"), Suggestions = c("Pair with apples, sliced pears OR a sampling of olives and thin sliced salami. Pass around slices of baguette.", 
"Serve with a substantial wheat cracker and apples or grapes.", 
"Rajas (blistered chile strips) fresh corn tortillas", "Table water crackers, raw nuts (almond, walnuts)", 
"Nutty brown bread, grapes", "Server with dried fruits, whole grain, nutty breads, nuts" 
)), .Names = c("Wine", "Cheese", "Suggestions"), row.names = c(NA, 
6L), class = "data.frame") 
+0

Было бы полезно, если бы вы могли отредактировать свой вопрос, включив данные примера в формат R-parseable. Например. 'dput (dfA)' и 'dput (dfB)'. –

+0

@CurtF. Я добавил свои данные примера, я был обеспокоен тем, что это может быть слишком запутанным, поэтому я удалил его и поставил приведенный пример. –

+1

Я не уверен, что использовать для 'DFA'. у вин DFB есть куча лишних пробелов, поэтому вы можете использовать это для запятой 'cheesePairing $ Wine <- gsub ('\\ s {2,}', ',', df $ Wine)' и теперь используйте один из ответов в [этом вопросе] (http://stackoverflow.com/questions/28285169/split-comma-separated-column-entry-into-rows) или другие аналогичные – rawr

ответ

2

Построение ответа Курта, я думаю, я нашел более эффективное решение ... предполагая, что я правильно истолковал вашу цель.

Мой прокомментированный код приведен ниже. Вы должны иметь возможность запускать это как есть и получать желаемый dfC. Следует отметить, что я предположил (исходя из ваших фактических данных), что разделитель dfB $ Index делителя равен «\ r \ n».

# set up fake data 
dfA<-data.frame(Index=c('1','2','3','4'), X=c('alpha','beta','gamma','delta')) 
dfB<-data.frame(Index=c('1 \r\n 4','3 \r\n 2 \r\n 1','4 \r\n 1 \r\n 2','3'), X=c('alpha','beta','gamma','delta')) 

dfA$Index<-as.character(dfA$Index) 
dfA$X<-as.character(dfA$X) 
dfB$Index<-as.character(dfB$Index) 
dfB$X<-as.character(dfB$X) 


dfB_index_parsed<-strsplit(x=dfB$Index,"\r\n") # split Index of dfB by delimiter "\r\n" and store in a list 
names(dfB_index_parsed)<-dfB$X 
dfB_split_num<-lapply(dfB_index_parsed, length) # find the number of splits per row of dfB and store in a list 
dfB_split_num_vec<-do.call('c', dfB_split_num) # convert number of splits above from list to vector 

g<-do.call('c',dfB_index_parsed) # store all split values in a single vector 
g<-gsub(' ','',g) # remove trailing/leading spaces that occur after split 
names(g)<-rep(names(dfB_split_num_vec), dfB_split_num_vec) # associate each split Index from dfB with X from dfB 
g<-g[g %in% dfA$Index] # check which dfB$Index are in dfA$Index 

dfC<-data.frame(Index=g, X=names(g)) # construct data.frame 
+0

Когда я запускаю этот Я закончил с пустой картой данных, но первые шаги пары, кажется, идут в правильном направлении.По какой-то причине соскабливание создало много лишнего, поэтому на третьем шаге количество разделов полностью отключено. Я попытаюсь удалить что-нибудь пустое и посмотреть, поможет ли это –

+0

О, странно. Я просто копировал/поместил свой код в отдельный сеанс R, и он прошел нормально. В любом случае, рад услышать, что это несколько полезно. Я думаю, что функции strsplit() + gsub() будут иметь решающее значение для любой стратегии решения этой проблемы. regexpr() также может оказаться полезным. Также проверьте, есть ли у скребок, который вы используете, встроенная функция для работы с этими результатами scrape. – AOGSTA

+0

Есть ли доказательства того, что это на самом деле более эффективно? В любом случае, хороший ответ и +1 от меня. –

0

Во-первых, позвольте мне представить функциональную ответ на свой вопрос. Я сомневаюсь, что мой ответ очень эффективен, но он работает.

# construct toy data 
dfA <- data.frame(index = 1:4, X = letters[1:4]) 

dfB <- data.frame(X = letters[1:4]) 
dfB$list_elements <- list(c(1, 4), c(3, 2, 1), c(4, 1, 2), c(3)) 

# define function that provides solution 

unlist_merge_df <- function(listed_df, reference_df){ 
    # reference_df assumed to have columns "X" and "index" 
    # listed_df assumed to have column "list_elements" 
    df_out <- data.frame(index = c(), X = c()) 
    my_list <- listed_df$list_elements 
    for(idx in 1:length(my_list)){ 
     df_out <- rbind(df_out, 
         data.frame(index = my_list[[idx]], 
            X = listed_df[idx, 'X']) 
         ) 
    } 
    return(df_out) 
} 

# call the function 
dfC <- unlist_merge_df(dfB, dfA) 

# show output in human and R-parseable formats 
dfC 

dput(dfC) 

Выход:

index X 
1 1 a 
2 4 a 
3 3 b 
4 2 b 
5 1 b 
6 4 c 
7 1 c 
8 2 c 
9 3 d 

structure(list(index = c(1, 4, 3, 2, 1, 4, 1, 2, 3), X = structure(c(1L, 
1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L), .Label = c("a", "b", "c", "d" 
), class = "factor")), .Names = c("index", "X"), row.names = c(NA, 
9L), class = "data.frame") 

Во-вторых, позвольте мне сказать, что ситуация вы в не очень желательны. Если вы можете избежать этого, вы, вероятно, должны. Либо не использовать кадры данных вообще, а только использовать списки, или вообще не конструировать перечисленные фреймы данных (если можете) и напрямую построить желаемый вывод.

+1

спасибо, я знаю, что это не идеальная ситуация. Я получил данные через веб-скребок, и я пытаюсь использовать его для базы данных, но он выглядит так, как будто мне, возможно, нужно просто объяснять, как это происходит и быть более явным в моих запросах базы данных. –

Смежные вопросы