Как создать столбцы из списка в для l oop, используя mutate - PullRequest
2 голосов
/ 28 апреля 2020

Мне было интересно, есть ли способ создать несколько столбцов из списка в R, используя функцию mutate() в пределах для для l oop.

Вот пример того, что я имею в виду:

Проблема:

У меня есть фрейм данных df, который имеет 2 столбца: категорию и рейтинг. Я хочу добавить столбец для каждого элемента df$category, и в этом столбце я хочу 1, если столбец категории соответствует итератору.

library(dplyr)

df <- tibble(
  category = c("Art","Technology","Finance"),
  rating = c(100,95,50)
)

Делая это вручную, я мог бы сделать:

df <-
  df %>% 
  mutate(art = ifelse(category == "Art", 1,0))

Однако, что происходит, когда у меня 50 категорий? (Что близко к тому, что у меня есть в моей первоначальной проблеме. Это заняло бы много времени!)

То, что я пытался:

category_names <- df$category

for(name in category_names){

  df <-
    df %>% 
    mutate(name = ifelse(category == name, 1,0))

}

К сожалению, это не похоже на работу.

Буду признателен за любую информацию по этому вопросу!

Полный код:

library(dplyr)

#Creates tibble
df <- tibble(
  category = c("Art","Technology","Finance"),
  rating = c(100,95,50)
)

#Showcases the operation I would like to loop over df
df <-
  df %>% 
  mutate(art = ifelse(category == "Art", 1,0))

#Creates a variable for clarity
category_names <- df$category

#For loop I tried
for(name in category_names){

  df <-
    df %>% 
    mutate(name = ifelse(category == name, 1,0))

}

Я осознаю, что то, что я по сути делаю, является формой model.matrix(); однако, прежде чем я узнал об этой функции, я все еще был озадачен, почему то, что я делал раньше, не работало.

1 Ответ

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

Мы можем использовать pivot_wider после создания столбца последовательности

library(dplyr)
library(tidyr)
df %>% 
    mutate(rn = row_number(), n = 1) %>% 
    pivot_wider(names_from = category, values_from = n, 
             values_fill = list(n = 0)) %>%
    select(-rn)
# A tibble: 3 x 4
#  rating   Art Technology Finance
#   <dbl> <dbl>      <dbl>   <dbl>
#1    100     1          0       0
#2     95     0          1       0
#3     50     0          0       1

Или другой вариант: map

library(purrr)
map_dfc(unique(df$category),  ~  df %>%
                                 transmute(!! .x := +(category == .x))) %>% 
     bind_cols(df, .)
# A tibble: 3 x 5
#  category   rating   Art Technology Finance
#* <chr>       <dbl> <int>      <int>   <int>
#1 Art           100     1          0       0
#2 Technology     95     0          1       0
#3 Finance        50     0          0       1

Если нам нужен for l oop

for(name in category_names) df <- df %>% mutate(!! name := +(category == name))

Или в base R с table

cbind(df, as.data.frame.matrix(table(seq_len(nrow(df)), df$category)))
#    category rating Art Finance Technology
#1        Art    100   1       0          0
#2 Technology     95   0       0          1
#3    Finance     50   0       1          0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...