在R函数中使用字符串变量进行数据过滤的报错问题咨询
我有一个包含多国数据的面板DataFrame,数据结构如下:
| Country | Date | Value |
|---|---|---|
| Austria | 1956-01-01 | 1.5 |
| Sweden | 1956-01-01 | 1.2 |
| UnitedKingdom | 1956-01-01 | 1.3 |
| Austria | 1957-01-01 | 1.6 |
| Sweden | 1957-01-01 | 1.0 |
| UnitedKingdom | 1957-01-01 | 1.8 |
我希望编写一个函数,筛选出指定国家和英国的数据用于图表对比,编写的函数代码如下:
PubHaus <- function(df, Nation) { df %>% filter(Country == {{ Nation }} | Country == "Unitedkingdom" ) %>% ggplot(aes(x = Date, y = Value, color = Country)) + geom_line(size = 1.2) + geom_hline(yintercept = 0) + geom_vline(xintercept = as.POSIXct(as.Date("1948-01-01"))) + labs(title = "Gross Public Housebuilding") }
执行PubHaus(Combined, Sweden)时出现如下报错:
Error: Problem with
filter()input..1.
i Input..1isCountry == Sweden | Country == "Unitedkingdom".
x dims [product 532] do not match the length of object [1180]
Runrlang::last_error()to see where the error occurred.
我推测该错误与无法将Nation变量定义为字符串有关,但显然直接使用filter(Country == "Nation")无法筛选出目标国家。请问我哪里出错了,该如何修复这个问题?
你的问题其实出在两个细节上,我们逐一解决:
1. 大小写匹配错误
首先看数据里的英国是UnitedKingdom(首字母K大写),但你代码里写的是"Unitedkingdom"(k小写)——这会导致英国的数据根本筛选不出来,同时这种不匹配也可能触发维度相关的报错。
2. 参数传递的逻辑问题
当你调用PubHaus(Combined, Sweden)时,Sweden被R当作了一个变量名,而不是字符串。如果你没有提前定义名为Sweden的变量,R就会尝试把它当作对象去匹配,最终引发维度不匹配的错误。
下面给你两种修复方案,按需选择:
方案一:传递字符串参数(简单直观)
修改函数,让Nation直接接收字符串参数,不需要用{{ }}语法:
PubHaus <- function(df, Nation) { df %>% # 修正英国的大小写,用%in%简化筛选逻辑 filter(Country %in% c(Nation, "UnitedKingdom")) %>% ggplot(aes(x = Date, y = Value, color = Country)) + geom_line(size = 1.2) + geom_hline(yintercept = 0) + geom_vline(xintercept = as.POSIXct(as.Date("1948-01-01"))) + labs(title = "Gross Public Housebuilding") }
调用时需要传入字符串:
PubHaus(Combined, "Sweden")
方案二:保留无引号调用(非标准求值)
如果你想保持调用时不用加引号的写法,需要把传入的符号转为字符串,同时修正大小写:
PubHaus <- function(df, Nation) { # 将传入的无引号名称转为字符串 nation_str <- rlang::as_name(rlang::enquo(Nation)) df %>% filter(Country %in% c(nation_str, "UnitedKingdom")) %>% ggplot(aes(x = Date, y = Value, color = Country)) + geom_line(size = 1.2) + geom_hline(yintercept = 0) + geom_vline(xintercept = as.POSIXct(as.Date("1948-01-01"))) + labs(title = "Gross Public Housebuilding") }
这样调用时就可以不用加引号:
PubHaus(Combined, Sweden)
另外,用%in%替代多个|条件会让代码更简洁,后续如果要添加更多对比国家,修改起来也更方便。
内容的提问来源于stack exchange,提问作者Samuel

