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

如何将多列身高体重数据转换为结构化表格并生成appt_num列?

问题描述

需要将如下原始表格:

record_idheight_1height_1_v1height_1_v1_v1weight_1weight_1_v1weight_1_v1_v1
10NANA5ft6inNANA154
105ft6inNANA152NANA
10NA5ft6inNANA131NA
11NANA5.11NANA138
11NA5.11NANA131NA

转换为目标结构的表格:

record_idappt_numheightweight
1015ft6in152
1025ft6in153
1035ft6in154
1115.11131
1125.11138

尝试过pivot_longer()、gather()未成功,用coalesce()接近目标但无法生成appt_num列,求实现方法。

解决方案

可以通过拆分列名分组+重塑数据的方式实现,核心是用pivot_longer拆分出测量类型和预约序号,再整理有效数据并生成appt_num:

library(tidyverse)

# 模拟原始数据
df <- tibble(
  record_id = c(10,10,10,11,11),
  height_1 = c(NA, "5ft6in", NA, NA, NA),
  height_1_v1 = c(NA, NA, "5ft6in", NA, "5.11"),
  height_1_v1_v1 = c("5ft6in", NA, NA, "5.11", NA),
  weight_1 = c(NA, 152, NA, NA, NA),
  weight_1_v1 = c(NA, NA, 153, NA, 131),
  weight_1_v1_v1 = c(154, NA, NA, 138, NA)
)

# 数据转换步骤
result <- df %>%
  # 把所有height/weight列转为长格式,拆分列名为测量类型和版本号
  pivot_longer(
    cols = -record_id,
    names_to = c("measure", "version"),
    names_pattern = "(height|weight)_(.*)",
    values_drop_na = TRUE
  ) %>%
  # 给每个record_id+measure分组,计算预约序号
  group_by(record_id, measure) %>%
  # 通过统计版本号中"v"的数量+1,生成连续的appt_num
  mutate(appt_num = dense_rank(str_count(version, "v") + 1)) %>%
  ungroup() %>%
  # 转回宽格式,拆分出height和weight列
  pivot_wider(
    id_cols = c(record_id, appt_num),
    names_from = measure,
    values_from = value
  ) %>%
  # 按record_id和appt_num排序
  arrange(record_id, appt_num)

代码解释

  1. 第一步pivot_longer:将所有height/weight相关列转为长格式,用正则names_pattern拆分出测量类型(height/weight)和版本标识(1、1_v1等),同时自动过滤NA值。
  2. 生成appt_num:按record_id和measure分组,通过统计版本标识中"v"的数量+1,得到对应的预约序号,再用dense_rank确保序号连续无断层。
  3. 第二步pivot_wider:将长格式的测量类型列重新拆分为height和weight列,最终得到目标结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 04:01:09