我想知道是否有一种方法可以在for循环中使用mutate()
函数从R中的列表创建多个列。
这是我的意思的示例:
问题:
我有一个数据框df
,其中有2列:类别和等级。我想为df$category
的每个元素添加一列,如果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()
的形式;但是,在我发现该功能之前,我仍然感到困惑,为什么之前的工作没有用。
答案 0 :(得分:3)
创建序列列后,我们可以使用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
循环
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