Соединить длинный фрейм данных с аккуратным фреймом данных - PullRequest
3 голосов
/ 07 мая 2019

У меня есть два кадра данных, как показано ниже:

df1 <- data.frame(Construction = c("Frame","Frame","Masonry","Fire Resistive","Masonry"),
                 Industry = c("Apartments","Restaurant","Condos","Condos","Condos"),
                 Size = c("[0-3)","[6-9)","[3-6)","[3-6)","9+"))
df2 <- data.frame(Category = c("Construction","Construction","Construction",
                               "Industry","Industry","Industry",
                               "Size","Size","Size","Size"),
                      Type = c("Frame","Masonry","Fire Resistive",
                               "Apartments","Restaurant","Condos",
                                "[0-3)","[3-6)","[6-9)","9+"),
                      Score1 = rnorm(10),
                      Score2 = rnorm(10),
                      Score3 = rnorm(10))

Я хочу присоединиться df2 к df1, чтобы Construction, Industry и Size каждый имели свои Score.

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

Вот формат, в котором я хочу, чтобы он выглядел следующим образом: (примечание: Score числа не совпадают.)

df3 <-  data.frame(Construction = c("Frame","Frame","Masonry","Fire Resistive","Masonry"),
                   Construction_Score1 = rnorm(5),
                   Construction_Score2 = rnorm(5),
                   Construction_Score3 = rnorm(5),
                   Industry = c("Apartments","Restaurant","Condos","Condos","Condos"),
                   Industry_Score1 = rnorm(5),
                   Industry_Score2 = rnorm(5),
                   Industry_Score3 = rnorm(5),
                   Size = c("[0-3)","[6-9)","[3-6)","[3-6)","9+"),
                   Size_Score1 = rnorm(5),
                   Size_Score2 = rnorm(5),
                   Size_Score3 = rnorm(5))

1 Ответ

3 голосов
/ 07 мая 2019

Идея состоит в том, чтобы объединить df1 и df2 на c("Construction","Industry","Size") и Type, а затем создать длинный фрейм данных, состоящий из того объединенного фрейма данных, который мы позже преобразуем в широкий, чтобы получить его вжелаемый формат.

mylist <- lapply(names(df1), function(col){
                              merge(x = df1, y = df2, 
                                    by.x = col, by.y = "Type", 
                                    all.x = TRUE)})

mydf <- do.call(rbind, mylist)

df3 <- reshape(mydf, idvar = c("Construction","Industry","Size"), 
                     timevar = "Category", 
                     direction = "wide")

Стоит отметить, что в качестве значения вашего Category столбца в df2, который, я думаю, у вас есть Scoreдолжно быть Size вместо того, чтобы соответствовать тому, что у вас есть в df3, а также тому, что было намекается в df1.



Обновление: ОтветОП дополнительный вопрос ;

  • Что, если есть другие столбцы, которые находятся в df1, но не df2?

Давайте сделаем df11, который имеетдругой столбец и примените тот же подход к этому:

df11 <- cbind(df1, a=1:5)

mydf <- do.call(rbind,
                      lapply(names(df11[1:3]), function(col){
                                               merge(x = df11, y = df2, 
                                                     by.x = col, by.y = "Type", 
                                                     all.x = TRUE)}))

df33 <- reshape(mydf, idvar = names(df11), 
               timevar = "Category", 
               direction = "wide")

Итак, вам просто нужно указать в lapply, какие столбцы df11 вы используете для merge с df2 и вreshape Вы включаете все столбцы из df11 независимо от того, совпадают они с df2 или нет.



Еще одна возможность с использованием пакета tidyverse (Спасибо @akrun за напоминание оmap_df):

map_df(names(df11)[1:3], ~ left_join(df11, df2, by = set_names("Type", .x))) %>% 
gather(mvar, mval, Score1:Score3) %>% 
unite(var, mvar, Category) %>% 
spread(var, mval)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...