将自定义函数应用于现有列以在R中的数据框中创建新列的最佳方法



我有一个数据帧,它有一个字符类型列,包含逗号分隔的数字字符串,即1, 2, 3, 4。我有一个自定义函数,我想将它按行应用于列中的每个值,以便获得一个新值,我可以将该值存储到数据帧df的新列中。

初始数据帧

A B str
1 1 1, 2, 5
1 2 NA
2 1 NA
2 2 1, 3

最终数据帧

A B str      res
1 1 1, 2, 5  2
1 2 NA       0
2 1 NA       0
2 2 1, 3     1

这是我的自定义函数getCounts

getCounts <- function(str, x, y){
if (is.na(str)){
return(as.integer(0))
}
vec <- as.integer(unlist(strsplit(str, ',')))
count <- 0
for (i in vec) {
if (i >= x & i <= y){
count <- count + 1
}
}
return(as.integer(count))
}

我最初尝试使用lapply,因为根据其他帖子,它似乎最适合使用,但不断出现错误,例如:

df <- df %>% mutate(res = lapply(df$str, getCounts(df$str, 0, 2)))
Error: Problem with `mutate()` input `res`. x missing value where TRUE/FALSE needed i Input `res` is `lapply(df$str, getCounts(df$str, 0, 2))`

似乎唯一有效的是当我使用mapply时,但我真的不明白为什么以及是否有更好的方法来做到这一点。

df <- df %>%mutate(res = mapply(getCounts, df$str, 0, 2))

如果我读对了,你应该可以只使用rowwise():

df %>%
rowwise() %>%
mutate(res = getCounts(str, 0, 2)) %>%
ungroup()

使用您的数据:

data.frame(
A = c(1,1,2,2),
B = c(1,2,1,2),
str = c('1, 2, 5', NA, NA, '1, 3')
) -> df
getCounts <- function(str, x, y){
if (is.na(str)){
return(as.integer(0))
}
vec <- as.integer(unlist(strsplit(str, ',')))
count <- 0
for (i in vec) {
if (i >= x & i <= y){
count <- count + 1
}
}
return(as.integer(count))
}
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
df %>%
rowwise() %>%
mutate(res = getCounts(str, 0, 2)) %>%
ungroup()
#> # A tibble: 4 x 4
#>       A     B str       res
#>   <dbl> <dbl> <chr>   <int>
#> 1     1     1 1, 2, 5     2
#> 2     1     2 <NA>        0
#> 3     2     1 <NA>        0
#> 4     2     2 1, 3        1

由reprex软件包(v1.0.0(于2021-03-17创建

您可以尝试Vectorize

df %>%
mutate(res = Vectorize(getCounts)(str, 0, 2))

sapply

df %>%
mutate(res = sapply(str, getCounts, x = 0, y = 2))

最新更新