R语言编写函数计算分年份分属性总加权均值时遇到长度不匹配错误及结果合理性疑问
一、函数报错的原因及修复方案
你调用函数时碰到的'x' and 'w' must have the same length错误,是由两个具体问题导致的:
年份筛选逻辑错误
当传入years = 2009:2010时,filter(df, year==years)无法正确筛选数据——year是数据中的列向量,years是长度为2的向量,==在这里会执行循环匹配,而非“包含”判断,导致筛选结果异常。正确写法应该用year %in% years,才能精准匹配指定年份的所有行。列引用方式错误
你传入的properties是字符串(比如"TR"),但直接将其作为weighted.mean的权重参数,相当于把单个字符串当成了长度为1的权重向量,而total是一列数据,长度远大于1,自然会触发长度不匹配的报错。这里需要用tidyeval语法将字符串转为对应列的引用,比如!!sym(properties)。
另外,我注意到你可能搞反了加权均值的参数顺序:根据你“按年份和属性计算两个地点的总加权均值”的需求,应该以total为权重,计算属性值的加权均值(公式为sum(属性值 * total) / sum(total)),对应weighted.mean(属性列, total),而非用属性值加权total。
修正后的函数如下:
library(dplyr) total.weighted.mean <- function(df, properties, years){ # 筛选指定年份的数据 dff <- filter(df, year %in% years) # 按年份+地点分组,计算属性的加权均值(以total为权重) res <- dff %>% group_by(year, location) %>% summarise(wt = weighted.mean(!!sym(properties), total), .groups = "drop") return(res) }
调用修正后的函数:
total.weighted.mean(df, properties = "TR", years = 2009:2010)
就能得到每个年份、每个地点对应的属性加权均值,完全符合你的需求。
二、外部计算的结果是否正确?
你在函数外部得到两个地点的wt均为732310,这个结果是不正确的,具体分析如下:
从你的原始数据来看:
- 2010年地点A有两行数据,
total均为822400,TR分别为0.09和0.13 - 2009年地点B有两行数据,
total均为565000,TR分别为0.05和0.07
如果按照“以total为权重计算属性加权均值”的逻辑:
- 地点A(2010年)的结果应为:
(822400*0.09 + 822400*0.13)/(822400+822400) = (0.09+0.13)/2 = 0.11 - 地点B(2009年)的结果应为:
(565000*0.05 + 565000*0.07)/(565000+565000) = (0.05+0.07)/2 = 0.06
你得到的732310与加权均值的逻辑完全不符,说明你外部计算的代码逻辑存在错误,才会出现这种相同的错误结果。
内容的提问来源于stack exchange,提问作者minoo

