Как преобразовать список символов в столбцы - PullRequest
1 голос
/ 12 октября 2019

У меня есть фрейм данных, столбец C является символом

df <- data.frame(A = c(13, 15, 17), B = c("yes", "no", "yes"), C = c("Mon, Thu, Sun", "Thu, Tue, Fri", "Sat, Mon, Wen"))

    A   B   C
1   13  yes Mon, Thu, Sun
2   15  no  Thu, Tue, Fri
3   17  yes Sat, Mon, Wen

Как преобразовать столбец data.frame C в:

    A   B   Sun Mon Tue Wen Thu Fri Sat
1   13  yes 1   1   0   0   1   0   0
2   15  no  0   0   1   0   1   1   0
3   17  yes 0   1   0   1   0   0   1

Ответы [ 3 ]

2 голосов
/ 12 октября 2019

Преобразовать его в длинную форму, используя separate_rows, добавить столбец значений и преобразовать C в коэффициент, а затем распространить его обратно в широкую форму.

library(dplyr)
library(tidyr)

days.abb <- c("Sun", "Mon", "Tue", "Wen", "Thu", "Fri", "Sat")
df %>%
  separate_rows(C) %>%
  mutate(value = 1, C = factor(C, days.abb)) %>%
  spread(C, value, fill = 0)

, что дает:

   A   B Sun Mon Tue Wen Thu Fri Sat
1 13 yes   1   1   0   0   1   0   0
2 15  no   0   0   1   0   1   1   0
3 17 yes   0   1   0   1   0   0   1
1 голос
/ 12 октября 2019

Подход с основанием R:

  1. Применяется к столбцу C, замените ",\\s" (запятая с последующим пробелом) на "|"
  2. Используйте grepl с результирующими регулярными выражениями, чтобы проверить, какие дни в days.abb присутствуют
  3. Объединить результирующие двоичные векторы по строкам и cbind с существующими столбцами A и B
## data
df <- data.frame(
    A = c(13, 15, 17), 
    B = c("yes", "no", "yes"), 
    C = c("Mon, Thu, Sun", "Thu, Tue, Fri", "Sat, Mon, Wen")
)

## abbreviated weekdays
days.abb <- c("Sun", "Mon", "Tue", "Wen", "Thu", "Fri", "Sat")

## find weekday indices for each character in column C
df1 <- cbind(df[, -3], t(sapply(df[, 3], function(x) 1 * grepl(gsub(",\\s", "|", x), days.abb))))

## update column names
setNames(df1, c("A", "B", days.abb)) 
#>    A   B Sun Mon Tue Wen Thu Fri Sat
#> 1 13 yes   1   1   0   0   1   0   0
#> 2 15  no   0   0   1   0   1   1   0
#> 3 17 yes   0   1   0   1   0   0   1
1 голос
/ 12 октября 2019

Один dplyr и tidyr параметр может быть:

df %>%
 mutate(C = strsplit(as.character(C), ", ", fixed = TRUE)) %>%
 unnest(C) %>%
 mutate(C_val = 1) %>%
 pivot_wider(names_from = C, values_from = C_val, values_fill = list(C_val = 0))

      A B       Mon   Thu   Sun   Tue   Fri   Sat   Wen
  <dbl> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1    13 yes       1     1     1     0     0     0     0
2    15 no        0     1     0     1     1     0     0
3    17 yes       1     0     0     0     0     1     1

Или альтернативно:

df %>%
 separate_rows(C) %>%
 mutate(C_val = 1) %>%
 pivot_wider(names_from = C, values_from = C_val, values_fill = list(C_val = 0))
...