Создать столбцы на основе количества в data.table - PullRequest
1 голос
/ 17 февраля 2020

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

Col1  Col2   Col3  Col4 
1     7000     73     6  
1     7000     73     7   
1     7000     73     8   
1     7000     73     9   
1     7000     73    10   
1     7000     73    11   
1     7000     73    12   
1     4000    117     6 
1     4000    117     9  

Я хочу посчитать число на Col1 и Col2. А затем на основе подсчета создать 5 новых столбцов. Я знаю, как считать, но как я могу создать 5 новых столбцов на основе количества.

Col1  Col2   Count   NewCol1  NewCol2  NewCol3  NewCol4  NewCol5  
1     7000       7         6        7        8        9       10  
1     4000       2         6        9        NA      NA       NA  

Col3 фактически можно игнорировать.

Есть одна вещь, которая Count варьируется от 1 до более чем 5. Поэтому, если Count > 5, мне не нужно иметь NewCol6, NewCol7 и т. Д. c.

Ответы [ 2 ]

2 голосов
/ 17 февраля 2020

Мы создаем столбец частоты с «add_count», сгруппированный по «Col1», «Col2», затем создаем столбец имен последовательности («nm1»), используем complete, чтобы расширить данные для отсутствующих комбинаций и изменить их на « широкоформатный формат с pivot_wider

library(dplyr)
library(tidyr)
library(stringr)
df1 %>%
    add_count(Col1, Col2) %>% 
    group_by(Col1, Col2) %>%
    slice(seq_len(5)) %>%
    mutate(nm1 = str_c("NewCol", row_number())) %>% 
    complete(nm1 = str_c("NewCol", 1:5)) %>%
    ungroup %>% 
    dplyr::select(-Col3) %>% 
    fill(n) %>%
    pivot_wider(names_from = nm1, values_from = Col4)
# A tibble: 2 x 8
#   Col1  Col2     n NewCol1 NewCol2 NewCol3 NewCol4 NewCol5
#  <int> <int> <int>   <int>   <int>   <int>   <int>   <int>
#1     1  4000     1       6      NA      NA      NA      NA
#2     1  7000     2       6       7      NA      NA      NA

со вторым набором данных

df2 %>%
        add_count(Col1, Col2) %>% 
        group_by(Col1, Col2) %>%
        slice(seq_len(5)) %>%
        mutate(nm1 = str_c("NewCol", row_number())) %>% 
        complete(nm1 = str_c("NewCol", 1:5)) %>%
        ungroup %>% 
        dplyr::select(-Col3) %>% 
        fill(n) %>%
        pivot_wider(names_from = nm1, values_from = Col4)
# A tibble: 2 x 8
#   Col1  Col2     n NewCol1 NewCol2 NewCol3 NewCol4 NewCol5
#  <int> <int> <int>   <int>   <int>   <int>   <int>   <int>
#1     1  4000     2       6       9      NA      NA      NA
#2     1  7000     7       6       7       8       9      10

или с использованием данных data.table

library(data.table)
dcast(setDT(df2)[, n  := .N, .(Col1, Col2)][,
   head(.SD, 5), .(Col1, Col2)], Col1 + Col2 + n ~  
  factor(paste0("NewCol", rowid(Col1, Col2)), 
       levels = paste0("NewCol", 1:5)), value.var = 'Col4')
#   Col1 Col2 n NewCol1 NewCol2 NewCol3 NewCol4 NewCol5
#1:    1 4000 2       6       9      NA      NA      NA
#2:    1 7000 7       6       7       8       9      10

df1 <- structure(list(Col1 = c(1L, 1L, 1L), Col2 = c(7000L, 7000L, 4000L
), Col3 = c(73L, 73L, 117L), Col4 = c(6L, 7L, 6L)), 
 class = "data.frame", row.names = c(NA, 
-3L))

df2 <- structure(list(Col1 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), 
    Col2 = c(7000L, 7000L, 7000L, 7000L, 7000L, 7000L, 7000L, 
    4000L, 4000L), Col3 = c(73L, 73L, 73L, 73L, 73L, 73L, 73L, 
    117L, 117L), Col4 = c(6L, 7L, 8L, 9L, 10L, 11L, 12L, 6L, 
    9L)), class = "data.frame", row.names = c(NA, -9L))
1 голос
/ 18 февраля 2020

Другой вариант data.table:

DT[, as.list(head(c(Col4, rep(NA_real_, 5L)), 5L)), .(Col1, Col2)]

Выход:

   Col1 Col2 V1 V2 V3 V4 V5
1:    1 7000  6  7  8  9 10
2:    1 4000  6  9 NA NA NA

данные:

library(data.table)
DT <- fread("Col1  Col2   Col3  Col4 
1     7000     73     6  
1     7000     73     7   
1     7000     73     8   
1     7000     73     9   
1     7000     73    10   
1     7000     73    11   
1     7000     73    12   
1     4000    117     6 
1     4000    117     9")
...