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

如何将自定义格式字符串解析为R DataFrame的单行多列?

问题:解析R DataFrame中类JSON格式的Stage列为单行多列

我正在处理一个包含Stage列的R DataFrame,该列采用类JSON的自定义字符串格式。我希望将其中的键值对解析为单独列,值对应原数据的同一行。

我尝试了正则提取、拆分及透视等方法,代码如下:

library(stringr)
library(dplyr)
library(tidyr)

# Sample dataframe
df <- data.frame(Stage = c("[{stage_type drive} {guid 1234a-f3f0-123b-c123d-e123456789f} {event_start_timestamp_ms 1684469450000} {event_end_timestamp_ms <nil>} {stage_number <nil>} {active true}]"))

# Extract key-value pairs using regular expressions
pattern <- "\\{(.*?)\\s(.*?)\\}"
df$pairs <- str_extract_all(df$Stage, pattern)

# Remove empty strings from pairs column
df$pairs <- lapply(df$pairs, function(x) x[x != ""])

# Split the pairs into separate columns
df_split <- df %>%
  unnest(pairs) %>%
  separate(pairs, into = c("key", "value"), sep = " ", remove = FALSE) %>%
  mutate(value = ifelse(value == "", NA, value)) %>%
  mutate(key = gsub('[^A-Za-z0-9_]','', key), 
         value = gsub('[^A-Za-z0-9_-]','', value)
) %>%
  select(-Stage)

df_pivot <- df_split %>%
  pivot_wider(names_from = key, values_from = value) %>%
  select(-c(key, pairs))

但最终得到6行数据,而我期望的是如下单行多列格式:

stage_typeguidevent_start_timestamp_msevent_end_timestamp_msstage_numberactive
drive1234a-f3f0-123b-c123d-e123456789f1684469450000nilniltrue

请问我的思路是否有误?该如何调整实现目标格式?


解决方案

你的思路方向是对的,问题出在**pivot_wider前没有保留原数据的行标识**,导致每个键值对被当成独立行处理,最终透视后出现重复行。另外正则和数据清理环节也可以优化,具体调整如下:

修正步骤:

  • 给原始数据添加行ID,确保透视时能将同一行的键值对聚合到一起
  • 优化正则提取,更精准匹配键值对,避免误拆分带特殊符号的字段值
  • 简化数据清理逻辑,正确处理<nil>这类特殊值

修正后的代码:

library(stringr)
library(dplyr)
library(tidyr)

# 样本数据(补全原代码的语法错误)
df <- data.frame(Stage = c("[{stage_type drive} {guid 1234a-f3f0-123b-c123d-e123456789f} {event_start_timestamp_ms 1684469450000} {event_end_timestamp_ms <nil>} {stage_number <nil>} {active true}]"))

# 1. 添加行ID,用于后续聚合同一原始行的键值对
df <- df %>% mutate(row_id = row_number())

# 2. 提取键值对:优化正则,精准匹配{key value}格式
df$pairs <- str_extract_all(df$Stage, "\\{([a-z_]+)\\s+([^}]+)\\}")

# 3. 展开键值对并拆分出key和value
df_split <- df %>%
  unnest(pairs) %>%
  mutate(
    key = str_match(pairs, "\\{([a-z_]+)\\s+")[,2],
    value = str_match(pairs, "\\s+([^}]+)\\}")[,2]
  ) %>%
  # 处理<nil>为指定的"nil"值
  mutate(value = ifelse(value == "<nil>", "nil", value)) %>%
  select(row_id, key, value)

# 4. 透视成宽表,按row_id聚合所有键值对到同一行
df_pivot <- df_split %>%
  pivot_wider(names_from = key, values_from = value) %>%
  select(-row_id) # 移除临时行ID

# 查看最终结果
print(df_pivot)

代码说明:

  • 行ID的作用:row_id是核心,它让pivot_wider知道哪些键值对属于同一原始行,避免拆分后分散成多行
  • 优化正则:\\{([a-z_]+)\\s+([^}]+)\\}专门匹配由字母下划线组成的键,以及大括号内直到末尾的所有内容作为值,不会拆分像guid这类带连字符的字段
  • 值处理:直接将<nil>替换为"nil",保留其他值的原始格式,避免过度正则清理破坏数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:23:09