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

如何在R中按分组提取首个实例并将列表垂直展开为列?

问题描述

原始数据结构如下:

age_group age_division    total_estimate zipcode  single_age
   <chr>            <dbl>       <dbl>      <dbl>      <list>    
1   0-4              2         10        51557   list(C(0, 0, 1, 1, 2, 2, 3, 3, 4, 4))
2   0-4              2         10        51557   list(C(0, 0, 1, 1, 2, 2, 3, 3, 4, 4))
3   0-4              2         10        51557   list(C(0, 0, 1, 1, 2, 2, 3, 3, 4, 4))
4   0-4              2         10        51557   list(C(0, 0, 1, 1, 2, 2, 3, 3, 4, 4))
5   0-4              2         10        51557   list(C(0, 0, 1, 1, 2, 2, 3, 3, 4, 4))
6   0-4              2         10        51557   list(C(0, 0, 1, 1, 2, 2, 3, 3, 4, 4))
7   0-4              2         10        51557   list(C(0, 0, 1, 1, 2, 2, 3, 3, 4, 4))
8   0-4              2         10        51557   list(C(0, 0, 1, 1, 2, 2, 3, 3, 4, 4))
9   0-4              2         10        51557   list(C(0, 0, 1, 1, 2, 2, 3, 3, 4, 4))
10  0-4              2         10        51557   list(C(0, 0, 1, 1, 2, 2, 3, 3, 4, 4))
11  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
12  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
13  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
14  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
15  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
16  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
17  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
18  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
19  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
20  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
21  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
22  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
23  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
24  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
25  0-4              3         15        51558   list(C(0, 0 ,0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4))
26  85-90            1         8         51559   list(C(0, 1, 2, 3, 4))
27  85-90            1         8         51559   list(C(0, 1, 2, 3, 4))
28  85-90            1         8         51559   list(C(0, 1, 2, 3, 4))
29  85-90            1         8         51559   list(C(0, 1, 2, 3, 4))
30  85-90            1         8         51559   list(C(0, 1, 2, 3, 4))
31  85-90            1         8         51559   list(C(0, 1, 2, 3, 4))

需求:针对每个唯一的zipcode和age_group,将对应的首个single_age列表垂直展开为数值列(而非列表类型),同时保留其他列的对应值,最终得到每行对应一个single_age数值的结构。

当前编写的代码生成的single_age仍为列表类型:

# Function to expand age groups
expand_age <- function(age_group, age_division) {
  age <- rep(seq(as.numeric(strsplit(age_group, "-")[[1]][1]), 
                 as.numeric(strsplit(age_group, "-")[[1]][2])), 
             each = age_division)
  return(list(age))
}

# Apply the function to each row of the dataframe using mutate
df <- df_1 %>%
  group_by(zipcode) %>%
  mutate(single_age = list(expand_age(first(age_group), first(age_division))))

期望输出格式:

age_group age_division    total_estimate zipcode  single_age
   <chr>            <dbl>       <dbl>      <dbl>      <dbl>    
1   0-4              2         10        51557          0
2   0-4              2         10        51557          0
3   0-4              2         10        51557          1
4   0-4              2         10        51557          1
5   0-4              2         10        51557          2
6   0-4              2         10        51557          2
7   0-4              2         10        51557          3
8   0-4              2         10        51557          3
9   0-4              2         10        51557          4
10  0-4              2         10        51557          4
11  0-4              3         15        51558          0
12  0-4              3         15        51558          0
13  0-4              3         15        51558          0
14  0-4              3         15        51558          1
15  0-4              3         15        51558          1
16  0-4              3         15        51558          1
17  0-4              3         15        51558          2
18  0-4              3         15        51558          2
19  0-4              3         15        51558          2
20  0-4              3         15        51558          3
21  0-4              3         15        51558          3
22  0-4              3         15        51558          3
23  0-4              3         15        51558          4
24  0-4              3         15        51558          4
25  0-4              3         15        51558          4
26  85-90            1         8         51559         85
27  85-90            1         8         51559         86
28  85-90            1         8         51559         87
29  85-90            1         8         51559         88
30  85-90            1         8         51559         89
31  85-90            1         8         51559         90
解决方案

问题分析

  1. 原函数expand_age返回列表,导致生成的single_age仍为列表类型;
  2. 分组仅按zipcode,但实际需要按zipcode+age_group分组(不同年龄组的生成规则不同);
  3. 仅用mutate无法将列表展开为多行,需要配合unnest扩展行。

修改后的代码

方法一:基于原函数调整

# 修改expand_age函数,直接返回向量而非列表
expand_age <- function(age_group, age_division) {
  age_range <- as.numeric(strsplit(age_group, "-")[[1]])
  rep(seq(age_range[1], age_range[2]), each = age_division)
}

# 按zipcode和age_group分组,生成single_age向量后展开行
df <- df_1 %>%
  group_by(zipcode, age_group) %>%
  # 提取每组的唯一属性值(同组内这些值一致)
  summarise(
    age_division = first(age_division),
    total_estimate = first(total_estimate),
    single_age = list(expand_age(age_group, age_division))
  ) %>%
  # 将列表列展开为多行
  unnest(single_age) %>%
  ungroup()

方法二:更简洁的tidyverse写法(无需单独函数)

df <- df_1 %>%
  # 保留每组的唯一属性记录
  distinct(zipcode, age_group, age_division, total_estimate) %>%
  rowwise() %>%
  mutate(
    age_range = as.numeric(strsplit(age_group, "-")[[1]]),
    single_age = list(rep(seq(age_range[1], age_range[2]), each = age_division))
  ) %>%
  # 展开列表为多行
  unnest(single_age) %>%
  ungroup() %>%
  # 调整列顺序与期望输出一致
  select(age_group, age_division, total_estimate, zipcode, single_age)

说明

  • 两种方法都会先保留每组的唯一属性,避免重复处理;
  • 通过list()包装生成的年龄向量,再用unnest()将其展开为多行,最终single_age会是数值类型;
  • 针对85-90这类年龄组,代码会自动根据age_group的范围生成正确的连续数值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 12:37:03