2017-01-17 8 views
-1

Со следующими данными ...purrr петля через колонки одного dataframe и условно заменить значения из другого dataframe

library(tidyverse) 

df_fac <- data_frame("author_1" = c("Ted", "Fred", NA, "Jim", "Tim"), 
       "role_1" = c("Faculty", "Faculty", "Staff", "Faculty", "Faculty"), 
       "author_2" = c(NA, "Will", NA, "Bill", NA), 
       "role_2" = c("Staff", "Faculty", "Staff", "Faculty", "Staff")) 

df_all <- data_frame("author_1" = c("Ted", "Fred", "Simon", "Jim", "Tim"), 
        "role_1" = c("Faculty", "Faculty", "Staff", "Faculty", "Faculty"), 
        "author_2" = c("Sam", "Will", "Noah", "Bill", "Luther"), 
        "role_2" = c("Staff", "Faculty", "Staff", "Faculty", "Staff")) 

Если «автор» столбцы в df_fac являются NA, я хотел бы, чтобы они наполняются в с соответствующим значением столбца от df_all с использованием функции map от purrr. Это то, что я в настоящее время обойтись без цикла:

df_test <- df_fac %>% 
    mutate(`author_1` = ifelse(is.na(`author_1`), df_all$`author_1`, `author_1`)) %>% 
    mutate(`author_2` = ifelse(is.na(`author_2`), df_all$`author_2`, `author_2`)) 

С map_df я могу сделать это Перебор столбцов в df_fac, но не в df_all (Как вы можете видеть, что только автор колонки 1).

df_test <- map_df(select(df_fac, matches("author.\\d$")), ~ { 
    ifelse(is.na(.), df_all$`author_1`, .) 
}) 

Есть ли способ иметь map_df перебрать select(df_all, matches("author.\\d$")) в то время как он перебирает select(df_fac, matches("author.\\d$"))?

В примере с игрушкой df_test должен иметь одинаковые столбцы и значения автора как df_all. Я пробовал:

df_test <- map_df(1:length(select(df_fac, matches("author.\\d$"))), ~ { 
    ifelse(is.na(select(df_fac, matches("author.\\d$"))[.]), 
    select(df_all, matches("author.\\d$"))[.], 
    select(df_fac, matches("author.\\d$"))[.]) 
}) 

Броски Error in bind_rows_(x, .id) : not compatible with STRSXP

df_test <- pmap_chr(list(is.na(select(df_fac, matches("author.\\d$"))), 
         select(df_all, matches("author.\\d$")), 
         select(df_fac, matches("author.\\d$"))), 
        ifelse) 

Броски Error: Element 2 has length 2, not 1 or 10.

Мне нужно использовать функцию matches как фактические данные, имеет много авторских колонок, смешанных с аналогичными именами переменных. Я могу уточнить, если это не ясно. Спасибо.

+0

В вашем примере, похоже, вы хотите, чтобы ваш вывод 'df_test' был идентичен' df_all'. Не могли бы вы улучшить его, чтобы лучше отражать ваши реальные данные и в чем проблема? Также: 'map' отлично, но уверены ли вы, что это соответствует вашим потребностям? Может быть, '* _join()' или что-то еще более подходит –

+0

@apom Блок кода с вызовами '' mutate' именно то, что я пытаюсь сделать, но используя цикл. В реальных данных есть столбцы и значения в 'df_fac', которые не находятся в' df_all' и наоборот, поэтому мой пример выше, чтобы принести отсутствующие имена авторов. На самом деле нет никакой проблемы с тем, как я это делаю сейчас, это всего лишь много повторяющихся кодов (я делаю то же самое с несколькими другими переменными, которые заканчиваются примерно 24 очень похожими вызовами 'mutate'). – Tunn

+0

Хорошо, еще один вопрос: можем ли мы с уверенностью предположить, что 'df_fac' и' df_all' упорядочены одинаково? Если мы каким-то образом 'cbind()' их, будут ли их строки всегда соответствовать? Или есть переменная, к которой можно присоединиться? –

ответ

2

Вы можете использовать map2_df для циклического перемещения по двум спискам одновременно. Использование dplyr::coalsece поможет заменить отсутствующие значения. Я использовал select, чтобы убедиться, что столбцы в df_all были такими же и в том же порядке, что и df_fac.

map2_df(df_fac, select(df_all, one_of(names(df_fac))), ~coalesce(.x, .y)) 

То же самое с помощью pmap:

pmap_df(list(df_fac, select(df_all, one_of(names(df_fac)))), coalesce) 

Вы можете использовать ifelse с map2, а также, наряду с формулой обозначения для обозначения двух различных списков, которые вы используете.

map2_df(df_fac, select(df_all, one_of(names(df_fac))), 
     ~ifelse(is.na(.x), .y, .x)) 
+0

Это довольно удивительно. Если бы futz с некоторыми подмножествами с исходными данными, но это хорошее решение. Благодарим вас за урок 'map2'. – Tunn

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

  • Нет связанных вопросов^_^