Разделение и комбинация столбцов фрейма данных в R - PullRequest
3 голосов
/ 26 мая 2020

У меня очень большой набор данных (около 500 тыс. Строк и 15 столбцов). один из столбцов содержит более одного символа, разделенного точкой с запятой, как показано ниже:

Date            a     b       c                  d  
01-01-2020     A1     B1     C1a;C1b            D1
30-12-2019     A2     B2     C2a;C2b;C2c        D2
33-5-2018      A3     B3     C3a;C3b;C3c;C3d    D3
20-11-2019     A4     B4     C4a;C4b            D4

Я хотел бы разделить столбец c, чтобы иметь только столбцы (cA и cB). Когда в c больше двух факторов, например, в столбцах 2 и 3, я хочу создать столько строк, сколько для каждой возможной уникальной комбинации C при прочих равных. Результат будет примерно таким:

Date            a     b      c_01   c_02            d 
01-01-2020     A1     B1     C1a    C1b            D1
30-12-2019     A2     B2     C2a    C2b            D2
30-12-2019     A2     B2     C2a    C2c            D2
30-12-2019     A2     B2     C2b    C2c            D2
33-5-2018      A3     B3     C3a    C3b            D3
33-5-2018      A3     B3     C3a    C3c            D3
33-5-2018      A3     B3     C3a    C3d            D3
33-5-2018      A3     B3     C3b    C3c            D3
33-5-2018      A3     B3     C3b    C3d            D3
33-5-2018      A3     B3     C3c    C3d            D3
20-11-2019     A4     B4     C4a    C4b            D4

Я попытался использовать csplit для создания одного столбца для каждого фактора, а затем создать for loop для каждой строки, но это не работает. Я также пытался с помощью функции apply создать что-то похожее на al oop, но набор данных слишком велик, и я продолжаю получать ошибки. Может кто поможет? Спасибо большое!

1 Ответ

1 голос
/ 26 мая 2020

Мы могли бы использовать strsplit, чтобы разделить столбец 'c' на ';', затем l oop поверх list с map, получить пару combn действий, преобразовать в данные .frame и unnest list столбца data.frame

library(dplyr)
library(tidyr)
library(purrr)
df1 %>%
   mutate(c = map(strsplit(c, ";"), ~ combn(.x, 2) %>% 
           t %>% 
            as.data.frame %>%
            set_names(c('c_01', 'c_02')))) %>%
   unnest(c(c))
# A tibble: 11 x 6
#   Date       a     b     c_01  c_02  d    
#   <chr>      <chr> <chr> <chr> <chr> <chr>
# 1 01-01-2020 A1    B1    C1a   C1b   D1   
# 2 30-12-2019 A2    B2    C2a   C2b   D2   
# 3 30-12-2019 A2    B2    C2a   C2c   D2   
# 4 30-12-2019 A2    B2    C2b   C2c   D2   
# 5 33-5-2018  A3    B3    C3a   C3b   D3   
# 6 33-5-2018  A3    B3    C3a   C3c   D3   
# 7 33-5-2018  A3    B3    C3a   C3d   D3   
# 8 33-5-2018  A3    B3    C3b   C3c   D3   
# 9 33-5-2018  A3    B3    C3b   C3d   D3   
#10 33-5-2018  A3    B3    C3c   C3d   D3   
#11 20-11-2019 A4    B4    C4a   C4b   D4   

Или используя base R

lst1 <- lapply(strsplit(df1$c, ";"), 
          function(x) as.data.frame(t(combn(x, 2))))
l1 <- sapply(lst1, nrow)
out <- cbind(df1[rep(seq_len(nrow(df1)), l1),c('Date', 'a', 'b', 'd')], 
         do.call(rbind, lst1))
row.names(out) <- NULL
names(out)[5:6] <- c("c_01", "c_02")
out
#         Date  a  b  d c_01 c_02
#1  01-01-2020 A1 B1 D1  C1a  C1b
#2  30-12-2019 A2 B2 D2  C2a  C2b
#3  30-12-2019 A2 B2 D2  C2a  C2c
#4  30-12-2019 A2 B2 D2  C2b  C2c
#5   33-5-2018 A3 B3 D3  C3a  C3b
#6   33-5-2018 A3 B3 D3  C3a  C3c
#7   33-5-2018 A3 B3 D3  C3a  C3d
#8   33-5-2018 A3 B3 D3  C3b  C3c
#9   33-5-2018 A3 B3 D3  C3b  C3d
#10  33-5-2018 A3 B3 D3  C3c  C3d
#11 20-11-2019 A4 B4 D4  C4a  C4b

data

df1 <- structure(list(Date = c("01-01-2020", "30-12-2019", "33-5-2018", 
"20-11-2019"), a = c("A1", "A2", "A3", "A4"), b = c("B1", "B2", 
"B3", "B4"), c = c("C1a;C1b", "C2a;C2b;C2c", "C3a;C3b;C3c;C3d", 
"C4a;C4b"), d = c("D1", "D2", "D3", "D4")), class = "data.frame",
row.names = c(NA, 
-4L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...