用于操作列表的自定义函数在单独工作时不能在 mutate 中工作
Custom function to manipulate list not working in mutate when it does work in isolation
我有一个数据框,其中一列是击键列表。然后我创建了一个自定义函数来将击键列表转换为最终单词。作为一个具体的例子,我从这个数据开始:
dat <- data.frame(word=c(1,1,2,2,2,2),
key=c("a","b","a","b","Backspace","c"))
然后我调用下面的命令来创建一个包含击键列表的列(重复是有意的,因为我需要保留每个单独的击键):
dat <- dat %>%
group_by(word) %>%
mutate(key_list = I(list(key))) %>%
ungroup()
这将创建一个数据框,其中前 2 行 key_list = a,b
,后 4 行 a,b,Backspace,c
。这是意料之中的事情。
然后我想将 key_list 连接成一个字符串。但是,我在下面创建了自定义函数,因为在遍历列表时,如果遇到“Backspace”,我需要删除最后一次击键。因此,函数看起来像:
library(tidyverse)
word_list_to_final_str <- function(word_list) {
final_list = c()
for (i in word_list) {
if (tolower(i) %in% c(letters)) {
final_list <- c(final_list, tolower(i))
}
else if (i == 'Backspace') {
final_list <- head(final_list, -1)
}
}
final_str <- str_c(final_list,collapse="")
return(final_str)
}
当我运行这个函数孤立的时候,它returns正确的结果:
19:13:11> word_list_to_final_str(c("a","b","Backspace","c"))
[1] "ac"
但是,当我 运行 mutate()
中的函数时,我得到一个包含所有“abababbackspacecabbackspacecabbackspacecabbackspacec”的附加列。
dat <- dat %>%
mutate(final_word = word_list_to_final_str(key_list))
显然某处函数没有清除列表,但我不明白在哪里。如何更改功能?
由于您有一个列表列,因此您需要映射该列表。您可以使用 purrr
使这变得非常简单
dat %>%
group_by(word) %>%
mutate(key_list = I(list(key))) %>%
mutate(final_word = purrr:::map_chr(key_list, word_list_to_final_str))
一个更“整洁”的方法是同时使用 tidyr::nest
dat %>%
tidyr::nest(key_list = c(key)) %>%
mutate(final_word = purrr::map_chr(key_list, ~word_list_to_final_str(.x$key)))
如果不编写函数,您可以这样做:
dat %>%
group_by(word)%>%
mutate(final_word = str_remove(str_c(key, collapse = ''), ".Backspace"))
# A tibble: 6 x 3
# Groups: word [2]
word key final_word
<dbl> <chr> <chr>
1 1 a ab
2 1 b ab
3 2 a ac
4 2 b ac
5 2 Backspace ac
6 2 c ac
我有一个数据框,其中一列是击键列表。然后我创建了一个自定义函数来将击键列表转换为最终单词。作为一个具体的例子,我从这个数据开始:
dat <- data.frame(word=c(1,1,2,2,2,2),
key=c("a","b","a","b","Backspace","c"))
然后我调用下面的命令来创建一个包含击键列表的列(重复是有意的,因为我需要保留每个单独的击键):
dat <- dat %>%
group_by(word) %>%
mutate(key_list = I(list(key))) %>%
ungroup()
这将创建一个数据框,其中前 2 行 key_list = a,b
,后 4 行 a,b,Backspace,c
。这是意料之中的事情。
然后我想将 key_list 连接成一个字符串。但是,我在下面创建了自定义函数,因为在遍历列表时,如果遇到“Backspace”,我需要删除最后一次击键。因此,函数看起来像:
library(tidyverse)
word_list_to_final_str <- function(word_list) {
final_list = c()
for (i in word_list) {
if (tolower(i) %in% c(letters)) {
final_list <- c(final_list, tolower(i))
}
else if (i == 'Backspace') {
final_list <- head(final_list, -1)
}
}
final_str <- str_c(final_list,collapse="")
return(final_str)
}
当我运行这个函数孤立的时候,它returns正确的结果:
19:13:11> word_list_to_final_str(c("a","b","Backspace","c"))
[1] "ac"
但是,当我 运行 mutate()
中的函数时,我得到一个包含所有“abababbackspacecabbackspacecabbackspacecabbackspacec”的附加列。
dat <- dat %>%
mutate(final_word = word_list_to_final_str(key_list))
显然某处函数没有清除列表,但我不明白在哪里。如何更改功能?
由于您有一个列表列,因此您需要映射该列表。您可以使用 purrr
使这变得非常简单
dat %>%
group_by(word) %>%
mutate(key_list = I(list(key))) %>%
mutate(final_word = purrr:::map_chr(key_list, word_list_to_final_str))
一个更“整洁”的方法是同时使用 tidyr::nest
dat %>%
tidyr::nest(key_list = c(key)) %>%
mutate(final_word = purrr::map_chr(key_list, ~word_list_to_final_str(.x$key)))
如果不编写函数,您可以这样做:
dat %>%
group_by(word)%>%
mutate(final_word = str_remove(str_c(key, collapse = ''), ".Backspace"))
# A tibble: 6 x 3
# Groups: word [2]
word key final_word
<dbl> <chr> <chr>
1 1 a ab
2 1 b ab
3 2 a ac
4 2 b ac
5 2 Backspace ac
6 2 c ac