首先,这是我关于StackOverflow的第一个问题,我希望我会写一个好方法。如果没有,请不要犹豫告诉我...对不起,我的英语水平很高!
我想使用dplyr中的mutate函数来更改data.frame列的类型,但事先不知道新类型。因此,我想动态创建函数名称(例如“ as.numeric”,“ as.factor”),并从另一个data.frame中获取新类型。
这是一个具体的示例(我想对具有100个以上变量的data.frames进行操作,因此您将了解我不想手动执行此操作!):</ p>
library(tidyverse)
df <- data.frame(Name = c("Roger", "Steve"), Age = c("40", "32"), stringsAsFactors = FALSE)
glimpse(df)
Observations: 2
Variables: 2
$ Name <chr> "Roger", "Steve"
$ Age <chr> "40", "32"
types <- data.frame(Field = c("Name", "Age"), OldType = c("character", "character"), NewType = c("factor", "integer"), stringsAsFactors = FALSE)
glimpse(types)
Observations: 2
Variables: 3
$ Field <chr> "Name", "Age"
$ OldType <chr> "character", "character"
$ NewType <chr> "factor", "integer"
我搜索了很长时间,发现了很多关于准引号的文档,我尝试了一些尝试,但是没有得到预期的结果。我做了两次尝试:
# First attempt
for(i in 1:nrow(types)){
field <- types$Field[i]
field_quo <- enquo(field)
new_type <- paste0("as.", types$NewType[i], "(", field, ")")
new_type_quo <- enquo(new_type)
df <- df %>% mutate(!!field_quo := !!new_type_quo)
}
glimpse(df)
Observations: 2
Variables: 2
$ Name <chr> "as.factor(Name)", "as.factor(Name)"
$ Age <chr> "as.integer(Age)", "as.integer(Age)"
=>函数调用被视为字符串,并且替换了列的值而不是其类型。
# Second attempt
for(i in 1:nrow(types)){
field <- types$Field[i]
field_quo <- ensym(field)
new_type <- paste0("as.", types$NewType[i], "(", field, ")")
new_type_quo <- ensym(new_type)
df <- df %>% mutate(!!field_quo := !!new_type_quo)
}
在这里我得到一个错误:
Error in mutate_impl(.data, dots) : Binding not found: as.factor(Name).
我猜想mutate函数会将括号中的内容作为一个完整的变量名称考虑在内?
我尝试了其他方法,但没有成功。我必须承认,我不是R专家,尽管文档质量很高,但我仍然难以充分理解准报价的概念。所以我知道我做错了事,但是我不知道为什么还是做错了……有人可以帮忙吗?
谢谢!
答案 0 :(得分:0)
有趣的问题。我想我在tidyverse的purrr包中找到了使用map2的解决方案。
# Data
df <- data.frame(Name = c("Roger", "Steve"), Age = c("40", "32"), stringsAsFactors = FALSE)
types <- data.frame(Field = c("Name", "Age"), OldType = c("character", "character"), NewType = c("factor", "integer"), stringsAsFactors = FALSE)
library(tidyverse)
# Create a column with function names that is needed. I.e. adding as.
types <- types %>%
mutate(newType2 = paste0("as.", NewType))
# Then loop over column names and functions
df2 <- map2_dfc(types$Field,
types$newType2,
~df %>%
select_(.x) %>%
mutate_all(.y)
) %>% as_tibble()
给你
> df2
# A tibble: 2 x 2
Name Age
<fct> <int>
1 Roger 40
2 Steve 32
但是为了轻松进行数据类型转换,请尝试。为每一列提供合适的数据类型。但是,它从不暗示因素。但随后您可以根据需要使用convert。
library(hablar)
df %>%
retype() %>%
convert(fct(Name))
答案 1 :(得分:0)
我认为您想要的是get
。这使您可以通过传入对象名称作为字符来检索对象,因此get('as.factor')
将返回as.factor
函数。使它适合您先前的尝试:
for(i in 1:nrow(types)) {
field <- sym(types$Field[i])
typeFun <- get(paste0('as.', types$NewType[i]))
df <- df %>%
mutate(!!field := typeFun(!!field))
}
glimpse(df)
Observations: 2
Variables: 2
$ Name <fct> Roger, Steve
$ Age <int> 40, 32