You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义R函数结果无法正确保留两位小数问题求助

问题背景

数据示例

dput(per_stack[1:4,])

输出结果:

structure(list(articles_ponderats2_migpunts = c(20.2083333333333, 
20.6666666666667, 23.8333333333333, 15.1666666666667), Tramspoblacio = structure(c(5L, 
4L, 4L, 4L), .Label = c("1 - 999", "1000 - 4999", "5000 - 9999", 
"10000 - 19999", "20000 - 49999", "50000 - 99999", "100000 - 200000", 
"Mayor de 200000"), class = "factor")), row.names = c(NA, 4L), class = "data.frame")

自定义汇总函数

funcio_resum <-function(x) {
  n<-NROW(x)
  mean<-mean(x)
  median <- median (x)
  min<-min (x)
  max<-max(x)
  q1 <- quantile(x, .25)
  q3 <- quantile(x, .75)
  SD<- sd(x)
  IQR <- IQR(x)
  quantile <- quantile(x, probs=seq(.1,.9, by =.1))
  hist<-hist(x)
  summary<-list(n=n,mean=mean, median = median, max=max,min=min, SD=SD, IQR = IQR)
  return(summary)
}

执行代码与报错

生成汇总表的代码:

resum <- tapply(index_articles_migpunts$articles_ponderats2_migpunts, index_articles_migpunts$Tramspoblacio, funcio_resum)
resum <- do.call (rbind, resum)

尝试用dplyr执行保留小数操作时报错:

resum %>% round(digits = 2)

错误信息:

Error in round(., digits = 2) : non-numeric argument to mathematical function

在函数内对均值、中位数等指标使用round后,结果仅显示整数(如显示8而非7.88),需排查原因。


问题原因与解决方法

1. round报错的核心原因

你猜测的hist对象并非关键问题(因为你没把它放进返回的summary列表),真正原因是:

  • tapply结合返回列表的函数后,得到的是分组列表;用do.call(rbind, resum)绑定后生成的是列表矩阵,每个单元格是单个数值的列表,而非直接的数值类型。这种结构下,round无法识别为可运算的数值向量,因此报错。

2. 函数内round只显示整数的原因

列表矩阵的元素是长度为1的列表,R在打印这类结构时会自动简化显示,导致原本保留两位小数的数值被截断为整数(实际值仍存在,但显示异常)。

3. 解决办法

方法一:修改自定义函数,返回数据框而非列表

将函数返回改为数据框,这样tapply后绑定得到的是标准数据框,可直接处理:

funcio_resum <-function(x) {
  n <- NROW(x)
  mean_val <- round(mean(x), 2)
  median_val <- round(median(x), 2)
  min_val <- round(min(x), 2)
  max_val <- round(max(x), 2)
  SD_val <- round(sd(x), 2)
  IQR_val <- round(IQR(x), 2)
  
  data.frame(n = n, 
             mean = mean_val, 
             median = median_val, 
             max = max_val, 
             min = min_val, 
             SD = SD_val, 
             IQR = IQR_val)
}

执行代码:

resum <- tapply(index_articles_migpunts$articles_ponderats2_migpunts, 
                index_articles_migpunts$Tramspoblacio, 
                funcio_resum)
resum <- do.call(rbind, resum)
# 此时可直接使用round,或函数内已完成保留小数
resum <- resum %>% round(digits = 2)

方法二:将列表矩阵转换为数值矩阵

无需修改函数,直接转换现有结构:

# 提取列表矩阵中的数值,转为数值矩阵
resum_num <- apply(resum, c(1,2), function(x) x[[1]])
# 保留两位小数
resum_num <- round(resum_num, 2)

方法三:用dplyr分组汇总更简洁

直接使用dplyr的分组功能,避免结构问题:

library(dplyr)
resum <- index_articles_migpunts %>%
  group_by(Tramspoblacio) %>%
  summarize(
    n = n(),
    mean = round(mean(articles_ponderats2_migpunts), 2),
    median = round(median(articles_ponderats2_migpunts), 2),
    min = round(min(articles_ponderats2_migpunts), 2),
    max = round(max(articles_ponderats2_migpunts), 2),
    SD = round(sd(articles_ponderats2_migpunts), 2),
    IQR = round(IQR(articles_ponderats2_migpunts), 2)
  )

内容的提问来源于stack exchange,提问作者FrancoBattiato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 04:43:17