Как я могу создать несколько столбцов одновременно, используя R, предпочтительно dplyr или data.table? - PullRequest
1 голос
/ 27 апреля 2020

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

Вот упрощенная версия моих данных:

df <- structure(list(City = structure(c(5L, 4L, 4L, 3L, 1L, 2L), .Label = c("Chico", 
"Lawndale", "Los Angeles", "San Francisco", "San Jose"), class = "factor"), 
    yq = c("20071", "20111", "20074", "20124", "20111", "20124"
    ), cyq_total = c(15582L, 33668L, 40848L, 89028L, 1069L, 178L
    )), row.names = c(NA, -6L), class = "data.frame")
           City    yq cyq_total
1      San Jose 20071     15582
2 San Francisco 20111     33668
3 San Francisco 20074     40848
4   Los Angeles 20124     89028
5         Chico 20111      1069
6      Lawndale 20124       178

Переменная cyq_total представляет количество вакансий в городе за квартал года (yq). Я хотел бы создать новые переменные с именами «Vac20071», «Vac20111» и т. Д., Где значением является cyq_total для данного города для данного года и квартала.

Это упрощено для моего примера, но по существу Я хочу, чтобы в столбце Vac20071 отображалось количество вакансий в каждом городе за квартал 2007 года. Аналогично для других кварталов года.

Желаемый результат:

  City          yq    cyq_total Vac20071 Vac20111 Vac20074 Vac20124
  <fct>         <chr>     <int>    <dbl>    <dbl>    <dbl>    <dbl>
1 San Jose      20071     15582    15582        0        0        0
2 San Francisco 20111     33668        0    33668    40848        0
3 San Francisco 20074     40848        0    33668    40848        0
4 Los Angeles   20124     89028        0        0        0    89028
5 Chico         20111      1069        0     1069        0        0
6 Lawndale      20124       178        0        0        0      178

Код, который мне нужно сделать это работает, но не эффективно. Я ищу лучший способ получить те же результаты, кроме копирования / вставки того же кода с небольшими изменениями:

df <- df %>% group_by(City) %>% mutate(Vac20071 = max(ifelse(yq == '20071', cyq_total, 0)))
df <- df %>% group_by(City) %>% mutate(Vac20111 = max(ifelse(yq == '20111', cyq_total, 0)))
df <- df %>% group_by(City) %>% mutate(Vac20074 = max(ifelse(yq == '20074', cyq_total, 0)))
df <- df %>% group_by(City) %>% mutate(Vac20124 = max(ifelse(yq == '20124', cyq_total, 0)))
df <- df %>% group_by(City) %>% mutate(Vac20111 = max(ifelse(yq == '20111', cyq_total, 0)))

Ответы [ 2 ]

3 голосов
/ 27 апреля 2020

Вы можете получить данные в широком формате и затем присоединиться.

library(dplyr)
library(tidyr)

df %>%
 pivot_wider(names_from = yq, values_from = cyq_total, names_prefix = 'Vac') %>%
 left_join(df, by = 'City')

# A tibble: 6 x 7
#  City          Vac20071 Vac20111 Vac20074 Vac20124 yq    cyq_total
#  <fct>            <int>    <int>    <int>    <int> <chr>     <int>
#1 San Jose         15582       NA       NA       NA 20071     15582
#2 San Francisco       NA    33668    40848       NA 20111     33668
#3 San Francisco       NA    33668    40848       NA 20074     40848
#4 Los Angeles         NA       NA       NA    89028 20124     89028
#5 Chico               NA     1069       NA       NA 20111      1069
#6 Lawndale            NA       NA       NA      178 20124       178

Эквивалентный подход в data.table, предложенный @ chinsoon12

library(data.table)

setDT(df)
dcast(df,City ~ paste0("Vac", yq), value.var="cyq_total", fill=0L)[df, on=.(City)]
2 голосов
/ 27 апреля 2020

Опция, использующая data.table с матричной цифрой c индексирование:

cols <- paste0("Vac", unique(df$yq))
setDT(df)[, (cols) := 0L]
df[, (cols) := {
    m <- as.matrix(.SD)
    ix <- match(paste0("Vac", yq), cols)
    m[cbind(rep(1L:.N, each=length(ix)), rep(ix, .N))] <- cyq_total
    as.data.table(m)
}, City, .SDcols=cols]
df
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...