我正在学习R进行数据分析,并使用this Kaggle数据集。遵循movie recommendation script的工作原理,但是当我尝试通过使dplyr
代码成为函数来概括代码时,我得到了一个错误:
我已经尝试对一些问题进行故障排除。看起来代码停止在filter
和mutate
函数中。
以下工作并给出了预期的输出。
genres <- df %>%
filter(nchar(genres)>2) %>%
mutate(
separated = lapply(genres, fromJSON)
) %>%
unnest(separated, .name_repair = "unique") %>%
select(id, title, keyword = name) %>%
mutate_if(is.character, factor)
将该代码包装在函数中会导致错误消息:
make_df <- function(list_df){
df %>%
filter(nchar(list_df)>2) %>%
mutate(
separated = lapply(list_df, fromJSON)
) %>%
unnest(separated, .name_repair = "unique") %>%
select(id, title, keyword = name) %>%
mutate_if(is.character, factor)
}
预期结果:
> head(genres)
# A tibble: 6 x 3
# id title keyword
# <dbl> <fct> <fct>
# 1 19995 Avatar Action
# 2 19995 Avatar Adventure
# 3 19995 Avatar Fantasy
# 4 19995 Avatar Science Fiction
# 5 285 Pirates of the Caribbean: At World's End Adventure
# 6 285 Pirates of the Caribbean: At World's End Fantasy
实际结果:
> make_df(genres)
# Error: Result must have length 4803, not 3
# --- Traceback ---
# 12. stop(structure(list(message = "Result must have length 4803, not 3",
# call = NULL, cppstack = NULL), class = c("Rcpp::exception",
# "C++Error", "error", "condition")))
# 11. filter_impl(.data, quo)
# 10. filter.tbl_df(., nchar(list_df) > 2)
# 9. filter(., nchar(list_df) > 2)
# 8. function_list[[i]](value)
# 7. freduce(value, `_function_list`)
# 6. `_fseq`(`_lhs`)
# 5. eval(quote(`_fseq`(`_lhs`)), env, env)
# 4. eval(quote(`_fseq`(`_lhs`)), env, env)
# 3. withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
# 2. df %>% filter(nchar(list_df) > 2) %>% mutate(separated = lapply(list_df,
# fromJSON)) %>% unnest(separated, .name_repair = "unique") %>%
# select(id, title, keyword = name) %>% mutate_if(is.character,
# factor)
# 1. make_df(genres)
不带过滤线的实际结果:
> make_df(genres)
# Error: Argument 'txt' must be a JSON string, URL or file.
# 15. base::stop(..., call. = FALSE)
# 14. stop("Argument 'txt' must be a JSON string, URL or file.")
# 13. FUN(X[[i]], ...)
# 12. lapply(list_df, fromJSON)
# 11. mutate_impl(.data, dots, caller_env())
# 10. mutate.tbl_df(., separated = lapply(list_df, fromJSON))
# 9. mutate(., separated = lapply(list_df, fromJSON))
# 8. function_list[[i]](value)
# 7. freduce(value, `_function_list`)
# 6. `_fseq`(`_lhs`)
# 5. eval(quote(`_fseq`(`_lhs`)), env, env)
# 4. eval(quote(`_fseq`(`_lhs`)), env, env)
# 3. withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
# 2. df %>% mutate(separated = lapply(list_df, fromJSON)) %>% unnest(separated,
# .name_repair = "unique") %>% select(id, title, keyword = name) %>%
# mutate_if(is.character, factor)
# 1. make_df(genres)
答案 0 :(得分:2)
您的问题实际上与整洁的编程有关。我指的是rlang syntax
您只需要在代码中添加{{}}。比它完美运行。
您可以使用以下方法解决此问题:
make_df <- function(list_df){
df %>%
filter(nchar({{ list_df }})>2) %>%
mutate(
separated = lapply({{ list_df }}, fromJSON)
) %>%
unnest(separated, .name_repair = "unique") %>%
select(id, title, keyword = name) %>%
mutate_if(is.character, factor)
}
比您可以执行(请确保删除您环境中的genres对象,否则请给他一个带有您以前的结果而不是字符串的小标题):
make_df(genres)
输出为:
# A tibble: 12,160 x 3
id title keyword
<dbl> <fct> <fct>
1 19995 Avatar Action
2 19995 Avatar Adventure
3 19995 Avatar Fantasy
4 19995 Avatar Science Fiction
5 285 Pirates of the Caribbean: At World's End Adventure
6 285 Pirates of the Caribbean: At World's End Fantasy
7 285 Pirates of the Caribbean: At World's End Action
8 206647 Spectre Action
9 206647 Spectre Adventure
10 206647 Spectre Crime
# ... with 12,150 more rows
答案 1 :(得分:1)
问题是您不能使用字符串来标识filter
和mutate
中的变量。
解决问题的最简单方法是使用filter_at
和mutate_at
:
make_df <- function(list_df){
df %>%
filter_at(vars(list_df), any_vars(nchar(.) > 2)) %>%
mutate_at(vars(list_df), list(seperated = ~lapply(.x, fromJSON)) %>%
unnest(separated, .name_repair = "unique") %>%
select(id, title, keyword = name) %>%
mutate_if(is.character, factor)
}
或者,您可以使用this question中所述的准引号。