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

如何对矩阵各列应用自定义函数?附普查区聚合街区收入计算需求

看起来你是要把普查区的分组收入数据汇总到街区层面,计算每个街区的家庭收入中位数对吧?这种分组数据的中位数计算得用加权中位数的思路,我来一步步帮你搞定。

首先先把你给出的数据整理清楚(注意看起来有个笔误,1500-19999应该是15000-19999吧?我后面会按修正后的逻辑处理):

# 模拟你的原始数据框(补全了部分未写完的数值)
inc_df <- data.frame(
  Income_Interval = c("2500-9999", "10000-14999", "15000-19999", "20000-24999", "25000-29999", "30000-34999", "35000-39999"),
  `San Francisco` = c(22457, 20708, 12701, 12106, 10129, 10310, 9028),
  `Bayview Hunters Point` = c(1057, 920, 626, 491, 554, 338, 383),
  `Bernal Heights` = c(287, 288, 145, 285, 238, 257, 180),
  `Castro/Upper Market` = c(329, 463, 148, 160, 328, 179, 150),
  `Chinatown` = c(1059, 1327, 867, 689, 167, 289, 120)
)

步骤1:处理收入区间,计算每个区间的中点

分组数据的中位数需要用区间中点作为代表值,我们可以写个小函数提取区间上下限并计算中点:

# 提取收入区间中点的函数
get_midpoint <- function(interval) {
  bounds <- as.numeric(strsplit(gsub(",", "", interval), "-")[[1]])
  (bounds[1] + bounds[2]) / 2
}

# 给数据框添加中点列
inc_df$Income_Midpoint <- sapply(inc_df$Income_Interval, get_midpoint)

步骤2:转换为长格式(tidy data)

宽格式数据不方便按街区分组计算,转成长格式更易操作:

library(tidyr)
library(dplyr)

inc_long <- inc_df %>%
  pivot_longer(
    cols = -c(Income_Interval, Income_Midpoint), 
    names_to = "Neighborhood", 
    values_to = "Household_Count"
  )

步骤3:计算每个街区的加权中位数

中位数的位置是总家庭数的一半,我们需要找到累计家庭数超过该位置的区间,再用线性插值计算精确中位数:

neighborhood_median <- inc_long %>%
  group_by(Neighborhood) %>%
  arrange(Income_Midpoint) %>%
  mutate(
    Cumulative_Count = cumsum(Household_Count),
    Total_Households = sum(Household_Count),
    Median_Position = Total_Households / 2
  ) %>%
  # 定位中位数所在的区间
  filter(Cumulative_Count >= Median_Position) %>%
  slice(1) %>% # 取第一个满足条件的区间
  mutate(
    # 用线性插值公式计算精确中位数:L + (N/2 - F)/f * w
    # L=区间下限,N=总家庭数,F=前一区间累计数,f=当前区间家庭数,w=区间宽度
    Interval_Lower = as.numeric(strsplit(gsub(",", "", Income_Interval), "-")[[1]][1]),
    Interval_Upper = as.numeric(strsplit(gsub(",", "", Income_Interval), "-")[[1]][2]),
    Interval_Width = Interval_Upper - Interval_Lower,
    Previous_Cumulative = ifelse(row_number() == 1, 0, lag(Cumulative_Count)),
    Median_Income = Interval_Lower + (Median_Position - Previous_Cumulative)/Household_Count * Interval_Width
  ) %>%
  select(Neighborhood, Total_Households, Median_Income) %>%
  ungroup()

# 查看最终结果
print(neighborhood_median)

几个注意点

  • 如果你的原始数据里1500-19999不是笔误,记得调整区间处理的逻辑;
  • 你提供的数据有未完成的行(比如35000-39999对应的部分数值),计算前一定要补全完整数据,否则结果会偏差;
  • 这种线性插值的方法是分组数据计算中位数的标准做法,比直接用中点加权更贴近真实中位数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:12:46