Error in substitute(FUN, env = parent.frame())[-1] :类别为‘symbol‘的对象不可以取子集 出错纠正

本文解决了在R语言中使用summaryBy函数时遇到的错误:类别为’symbol’的对象不可以取子集。通过检查mean函数是否被误赋值并重新加载base包中的mean函数来解决问题。

Error in substitute(FUN, env = parent.frame())[-1] :类别为’symbol’的对象不可以取子集

summaryBy()函数 mtcars举例

在近期的R语言学习中。在运用summaryBy()函数做多统计量描述统计时,一直被持续警告一个错误,Error in substitute(FUN, env = parent.frame())[-1] :类别为’symbol’的对象不可以取子集。
由于是R语言小白,多方面搜查也无果,后搜寻 env=parent.frame()的意思。勉强猜测是函数问题。
后来经过验证,确实是mean函数出现错误。
写下纠正错误的经过,加深对R语言的理解。

>mycars<-mtcars[c("mpg","hp","wt","am")]
>library(doBy)
>summaryBy(mpg+hp+wt~am,data=mycars,FUN=mean)
Error in substitute(FUN, env = parent.frame())[-1] : 
  类别为'symbol'的对象不可以取子集

在这里插入图片描述
后来我经过多方查询,试验,发现可能是 mean 函数在之前的学习中给它赋值了,导致在取用函数时R首先认定它是变量名称而非函数。
试验过程↓

>summaryBy(mpg+hp+wt~am,data=mycars,FUN=sum)
  am mpg.sum hp.sum wt.sum
1  0   325.8   3045 71.609
2  1   317.1   1649 31.343

在这里插入图片描述

接着试着敲了敲 mean 看看反应如何

>mean
         N.Amer   Europe     Asia   S.Amer Oceania Africa  Mid.Amer
1951 45939.00 21574.00 2876.000 1815.000    1646     89  555.0000
1956 60423.00 29990.00 4708.000 2568.000    2366   1411  733.0000
1957 64721.00 32510.00 5230.000 2695.000    2526   1546  773.0000
1958 68484.00 35218.00 6662.000 2845.000    2691   1663  836.0000
1959 71799.00 37598.00 6856.000 3000.000    2868   1769  911.0000
1960 76036.00 40341.00 8220.000 3145.000    3054   1905 1008.0000
1961 79831.00 43173.00 9053.000 3338.000    3224   2005 1076.0000
mean 66747.57 34343.43 6229.286 2772.286    2625   1484  841.7143

在这里插入图片描述
发现确实是之前的我学习时把mean给赋值了。(并且在退出时选择了保存)
于是从base包中调用mean函数。最终解决该问题。

>base::mean
function (x, ...) 
UseMethod("mean")
<bytecode: 0x000002465777ceb0>
<environment: namespace:base>
 >summaryBy(mpg+hp+wt~am,data = mtcars,FUN = base::mean)
  am mpg.base::mean hp.base::mean wt.base::mean
1  0       17.14737      160.2632      3.768895
2  1       24.39231      126.8462      2.411000

在这里插入图片描述

<think> 我们正在解决R语言中的错误:“错误于eval(substitute(expr), data, enclos = parent.frame()):对象'city'”。这个错误通常发生在使用诸如`with`、`within`、`subset`等函数时,它们使用非标准评估(NSE)来查找变量。错误表明在指定的数据环境(data)中找到名为'city'的对象。 可能的原因及解决办法: 1. **数据框(data frame)中确实没有'city'列**:检查数据框中是否存在名为'city'的列。可以使用`names(data)`或`colnames(data)`查看列名。 2. **拼写错误**:检查是否拼写错误(例如,大小写一致)。R是大小写敏感的。 3. **未正确指定数据参数**:在使用`with`等函数时,确保将包含'city'列的数据框作为`data`参数传入。 4. **使用attach函数**:虽然使用`attach`可以避免显式指定数据框,但推荐,因为它容易导致环境混乱。如果使用了`attach`,请检查是否正确附加了数据框,并考虑使用其他方法避免`attach`。 5. **变量在数据框中而在全局环境**:如果'city'是全局环境中的向量,而是数据框中的列,那么在使用`with(data, ...)`时,它会只在数据框`data`中查找,而会在全局环境中查找。解决方法: - 将全局环境中的变量合并到数据框中(如果合理的话)。 - 使用`$`运算符明确指定变量来源,例如`data$city`,或者使用`transform`、`mutate`(dplyr包)等函数。 6. **使用dplyr等包的非标准评估**:如果在使用dplyr包(如`mutate`、`filter`、`select`等)时出现此错误,可能是因为直接使用了对象名(非标准评估)。确保数据框包含该列,或者使用`.data`代词(例如`.data$city`)或`!!`(bang bang)操作符(在编程中使用时)。 7. **作用域问题**:在函数内部使用时,可能需要更小心地传递数据环境。考虑使用`data`参数显式传递数据框,或者使用`dplyr`的函数,它们更好地处理了数据掩码。 具体步骤: 假设我们有以下代码导致错误: ```r with(mydata, mean(city)) ``` 步骤1:确认数据框`mydata`中是否有`city`列。 ```r # 检查列名 names(mydata) # 或者 "city" %in% colnames(mydata) ``` 步骤2:如果列名存在拼写错误,更正它。 步骤3:如果列名存在,需要检查数据来源,并正确地导入数据或创建该列。 步骤4:如果确定列存在,但仍然报错,可能是因为数据框未正确传递。尝试使用显式引用: ```r mean(mydata$city) ``` 但是,如果在一个表达式中需要多个变量,使用显式引用可能会变得冗长。这时可以考虑使用`dplyr`包: ```r library(dplyr) mydata %>% summarise(mean_city = mean(city)) ``` 步骤5:在函数内部处理时,可能需要使用非标准评估的特殊处理。例如,在编写函数时,使用`eval`和`substitute`需要小心作用域。可以尝试使用`eval`的`envir`参数指定环境。 另外,在Shiny等交互式环境中,可能需要使用`req`或`validate`来确保数据可用。 步骤6:如果数据框是通过编程方式构建的,确保在构建过程中包含了`city`列,并且没有在后续被删除。 示例修正: 错误代码: ```r # 假设mydata中没有city列,或者列名是City(大写C) with(mydata, mean(city)) ``` 修正1(如果列名是City): ```r with(mydata, mean(City)) ``` 修正2(如果确实没有city列,但有一个类似的列,比如town): ```r with(mydata, mean(town)) ``` 修正3(使用dplyr): ```r mydata %>% summarise(mean_city = mean(city)) # 如果列存在 # 或者如果列名错误,先重命名 mydata %>% rename(city = Town) %>% summarise(mean_city = mean(city)) ``` 如果问题发生在函数中,例如: ```r my_function <- function(data, column) { with(data, mean(column)) } ``` 调用`my_function(mydata, city)`会出错,因为`column`在`data`中并是一个列名,而是一个变量名。此时应使用非标准评估的技巧,或者使用`[[`操作符: ```r my_function <- function(data, column) { mean(data[[column]]) } # 调用 my_function(mydata, "city") ``` 或者使用dplyr的编程接口(使用rlang): ```r library(dplyr) library(rlang) my_function <- function(data, column) { data %>% summarise(mean = mean(!!sym(column))) } # 调用 my_function(mydata, "city") ``` 总结:首先检查数据框中是否存在该列,然后检查拼写,最后考虑作用域问题。在函数中处理数据框的列时,推荐使用字符串列名和`[[`操作符,或者使用dplyr的整洁评估(tidy evaluation)。 如果用户的问题是在特定的代码上下文中,请提供更多代码细节以便更精确地解决。 </think>要解决R语言中的错误“错误于eval(substitute(expr), data, enclos = parent.frame()):对象'city'”,请按照以下步骤排查和修复: ### 1. **检查变量是否存在** ```r # 确认数据框是否包含'city'列 print(colnames(your_dataframe)) # 替换your_dataframe为实际数据框名 "city" %in% colnames(your_dataframe) # 应返回TRUE ``` ### 2. **检查变量名拼写** - R语言**区分大小写**:`City` ≠ `city` - 特殊字符需用反引号包裹: ```r your_dataframe$`city name` # 含空格的变量名 ``` ### 3. **检查数据作用域**(常见原因) 当使用`with()`、`subset()`等函数时: ```r # 错误示例(city在df中): with(df, mean(city)) # 解决方案: with(df, mean(df$city)) # 显式指定数据源 # 或 df$mean_city <- mean(df$city) # 避免非标准评估 ``` ### 4. **函数内变量作用域问题** 在自定义函数中: ```r # 错误示例 my_func <- function(data) { with(data, mean(city)) # city未定义 } # 解决方案:显式引用列 my_func <- function(data) { mean(data$city) # 正确作用域引用[^1] } ``` ### 5. **检查数据框加载状态** ```r # 确认数据框已加载 exists("your_dataframe") # 应返回TRUE # 确认列实际存在 head(your_dataframe) # 查看前几行数据 ``` ### 6. **修复列名错误** ```r # 重命名列 colnames(your_dataframe)[colnames(your_dataframe) == "wrong_city"] <- "city" ``` ### 7. **避免attach()函数** ```r # 推荐使用(易导致作用域混乱): attach(your_dataframe) mean(city) # 推荐替代方案: with(your_dataframe, mean(city)) # 或直接使用your_dataframe$city ``` ### 预防措施 1. **始终显式指定数据源**:优先使用`dataframe$column`语法 2. **检查数据导入**:使用`read.csv()`后立即运行`str(data)`验证结构 3. **使用tidyverse**:dplyr包更安全: ```r library(dplyr) your_dataframe %>% summarise(avg = mean(city, na.rm = TRUE)) ``` > **典型修复案例**: > 当错误出现在`subset()`中时: > ```r > # 错误代码 > subset(df, city == "New York") > > # 修复后(显式指定列) > subset(df, df$city == "New York") > ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

24442552

兄弟们...谢谢知识付费

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值