使用 summarize 和 for 循环从字符向量中获取列名
Use summarize and a for loop taking column names from a character vector
我有一个无法在此处共享的数据集,但我需要使用 for 循环创建列,并且列名应来自字符向量。下面我尝试使用 nycflights13 包中的航班数据集来复制我想要实现的目标。
install.packages("nycflights13")
library(nycflights13)
flights <- nycflights13::flights
flights <- flights[c(10, 16, 17)]
var_interest <- c("distance", "hour")
for (i in 1:length(var_interest)) {
flights %>% group_by(carrier) %>%
summarize(paste(var_interest[i], "n", sep = "_") = sum(paste(var_interest[i])))
}
此代码生成以下错误:
Error: unexpected '=' in:
" flights %>% group_by(carrier) %>%
summarize(paste(var_interest[i], "n", sep = "_") ="
> }
Error: unexpected '}' in "}"
我的实际数据集比这个例子更复杂,因此,我需要遵循这种方法。因此,如果您能帮我找到我在这里缺少的东西,将不胜感激!
代码可以修改为在将字符串转换为sym
bol之后评估(!!
)列,而在赋值的lhs
上(:=
)对字符串进行评估(!!
)
out <- vector('list', length(var_interest))
for (i in seq_along(var_interest)) {
out[[i]] <- flights %>%
group_by(carrier) %>%
summarize(!! paste(var_interest[i], "n", sep = "_") :=
sum(!! rlang::sym(var_interest[i])), .groups = 'drop')
}
lapply(out, head, 3)
#[[1]]
# A tibble: 3 x 2
# carrier distance_n
# <chr> <dbl>
#1 9E 9788152
#2 AA 43864584
#3 AS 1715028
#[[2]]
# A tibble: 3 x 2
# carrier hour_n
# <chr> <dbl>
#1 9E 266419
#2 AA 413361
#3 AS 9013
有多种方法可以传递字符串列名并对其求值。
- 如上所述,转换为
sym
bol 并计算 (!!
)。
- 利用
across
,它可以将不带引号的、字符串或列索引作为整数,即在这种情况下,我们甚至不需要任何循环
flights %>%
group_by(carrier) %>%
summarise(across(all_of(var_interest), ~
sum(., na.rm = TRUE), .names = '{.col}_n'),
.groups = 'drop')
# A tibble: 16 x 3
# carrier distance_n hour_n
# <chr> <dbl> <dbl>
# 1 9E 9788152 266419
# 2 AA 43864584 413361
# 3 AS 1715028 9013
# 4 B6 58384137 747278
# 5 DL 59507317 636932
# 6 EV 30498951 718187
# 7 F9 1109700 9441
# 8 FL 2167344 43960
# 9 HA 1704186 3324
#10 MQ 15033955 358779
#11 OO 16026 550
#12 UA 89705524 754410
#13 US 11365778 252595
#14 VX 12902327 63876
#15 WN 12229203 151366
#16 YV 225395 9300
一个简洁的方法可能是将它堆叠得更长而不是更宽:
install.packages("nycflights13")
library(nycflights13)
flights <- nycflights13::flights %>%
select(carrier,distance,hour)
by_carrier <- purrr::map_dfr( c('distance','hour'), function(x) {
flights %>%
dplyr::group_by(carrier) %>%
dplyr::summarize(n = sum(!!as.name(x))) %>%
dplyr::mutate(key = x)
})
如果您仍希望 for
循环附加列,您可以使用 !!as.name()
功能两次,例如
by_carrier <- NULL
for ( i in c('distance','hour')) {
df <-
flights %>%
dplyr::group_by(carrier) %>%
dplyr::summarize(!!as.name(i) := sum(!!as.name(i) ))
by_carrier <- bind_cols(by_carrier,df)
}
尽管您必须在该列之后清理 carrier
列。
我有一个无法在此处共享的数据集,但我需要使用 for 循环创建列,并且列名应来自字符向量。下面我尝试使用 nycflights13 包中的航班数据集来复制我想要实现的目标。
install.packages("nycflights13")
library(nycflights13)
flights <- nycflights13::flights
flights <- flights[c(10, 16, 17)]
var_interest <- c("distance", "hour")
for (i in 1:length(var_interest)) {
flights %>% group_by(carrier) %>%
summarize(paste(var_interest[i], "n", sep = "_") = sum(paste(var_interest[i])))
}
此代码生成以下错误:
Error: unexpected '=' in:
" flights %>% group_by(carrier) %>%
summarize(paste(var_interest[i], "n", sep = "_") ="
> }
Error: unexpected '}' in "}"
我的实际数据集比这个例子更复杂,因此,我需要遵循这种方法。因此,如果您能帮我找到我在这里缺少的东西,将不胜感激!
代码可以修改为在将字符串转换为sym
bol之后评估(!!
)列,而在赋值的lhs
上(:=
)对字符串进行评估(!!
)
out <- vector('list', length(var_interest))
for (i in seq_along(var_interest)) {
out[[i]] <- flights %>%
group_by(carrier) %>%
summarize(!! paste(var_interest[i], "n", sep = "_") :=
sum(!! rlang::sym(var_interest[i])), .groups = 'drop')
}
lapply(out, head, 3)
#[[1]]
# A tibble: 3 x 2
# carrier distance_n
# <chr> <dbl>
#1 9E 9788152
#2 AA 43864584
#3 AS 1715028
#[[2]]
# A tibble: 3 x 2
# carrier hour_n
# <chr> <dbl>
#1 9E 266419
#2 AA 413361
#3 AS 9013
有多种方法可以传递字符串列名并对其求值。
- 如上所述,转换为
sym
bol 并计算 (!!
)。 - 利用
across
,它可以将不带引号的、字符串或列索引作为整数,即在这种情况下,我们甚至不需要任何循环
flights %>%
group_by(carrier) %>%
summarise(across(all_of(var_interest), ~
sum(., na.rm = TRUE), .names = '{.col}_n'),
.groups = 'drop')
# A tibble: 16 x 3
# carrier distance_n hour_n
# <chr> <dbl> <dbl>
# 1 9E 9788152 266419
# 2 AA 43864584 413361
# 3 AS 1715028 9013
# 4 B6 58384137 747278
# 5 DL 59507317 636932
# 6 EV 30498951 718187
# 7 F9 1109700 9441
# 8 FL 2167344 43960
# 9 HA 1704186 3324
#10 MQ 15033955 358779
#11 OO 16026 550
#12 UA 89705524 754410
#13 US 11365778 252595
#14 VX 12902327 63876
#15 WN 12229203 151366
#16 YV 225395 9300
一个简洁的方法可能是将它堆叠得更长而不是更宽:
install.packages("nycflights13")
library(nycflights13)
flights <- nycflights13::flights %>%
select(carrier,distance,hour)
by_carrier <- purrr::map_dfr( c('distance','hour'), function(x) {
flights %>%
dplyr::group_by(carrier) %>%
dplyr::summarize(n = sum(!!as.name(x))) %>%
dplyr::mutate(key = x)
})
如果您仍希望 for
循环附加列,您可以使用 !!as.name()
功能两次,例如
by_carrier <- NULL
for ( i in c('distance','hour')) {
df <-
flights %>%
dplyr::group_by(carrier) %>%
dplyr::summarize(!!as.name(i) := sum(!!as.name(i) ))
by_carrier <- bind_cols(by_carrier,df)
}
尽管您必须在该列之后清理 carrier
列。