将数据框中的字符串向量转换为 R 中的分类变量

Turning vectors of strings in a dataframe into categorical variables in R

我是 R 的新手,我确信有一种方法可以在不使用循环的情况下执行以下操作,我对此比较熟悉。

举个例子,你有一堆每个人都喜欢的名字和水果:

name <- c("Alice", "Bob")
preference <- list(c("apple", "pear"), c("banana", "apple"))
df <- as.data.frame(cbind(name, preference))

如何将其转换为以下内容?

apple <- c(1, 1)
pear <- c(1, 0)
banana <- c(0, 1)
df2 <- data.frame(name, apple, pear, banana)

我的基本直觉是先提取所有水果,然后循环检查每个水果是否符合每一行的偏好:

fruits <- unique(unlist(df$preference))
for (fruit in fruits) {
    df <- df %>% rowwise %>% mutate("{fruit}" := fruit %in% preference)
}

这似乎可行,但我很确定有更好的方法。

df %>%
  unnest(everything()) %>%
  xtabs(~., .) %>%
  as.data.frame.matrix() %>%
  rownames_to_column('name')

   name apple banana pear
1 Alice     1      0    1
2   Bob     1      1    0

tidyverse(假设'preference'是一个list列),unnest然后'preference'再用pivot_wider重塑回到 'wide' 格式 values_fnlength

library(dplyr)
library(tidyr)
df %>% 
   unnest_longer(preference) %>%
    pivot_wider(names_from = preference, values_from = preference, 
      values_fn = length, values_fill = 0)

-输出

# A tibble: 2 × 4
  name  apple  pear banana
  <chr> <int> <int>  <int>
1 Alice     1     1      0
2 Bob       1     0      1

数据

df <- data.frame(name, preference = I(preference))

另一种可能的解决方案,基于 tidyr::separate_rowsjanitor::tabyl

library(tidyverse)

df %>% 
  separate_rows(everything(), sep="(?<=\w), (?=\w)") %>% 
  janitor::tabyl(name, preference)

#>   name apple banana pear
#>  Alice     1      0    1
#>    Bob     1      1    0