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

使用tidyr::separate拆分PDF数据时保留小数的技术求助

解决PDF抓取数据的拆分与数值精度保留问题

问题概述

从PDF表格导出的数据格式混乱,需要拆分出变量、单位和多列数值,存在几个难点:

  • 数据间的空格长度不固定
  • 部分数值带%后缀(比如11.48%)
  • 部分单位包含.%(比如wt.%)
  • 用tidyr::separate直接拆分时,小数会被错误截断成整数,丢失精度

原始数据如下:

df <- data.frame(Data = c("Ag, ppm  0.219 0.025 0.169 0.269  0.144 0.294 11.48%  22.96%   34.43%  0.208  0.230",
                          "Al, wt.%  5.27  0.119 5.03  5.50   4.91  5.62 2.25%   4.51%   6.76%   5.00  5.53"))

df$Method <- "XRF"

原拆分代码的问题:直接用separate且未指定正确分隔符,导致小数点被误判为分隔标记,加上convert=TRUE后数值被错误解析成整数。


解决方案

方案1:修正separate的分隔规则,分步拆分

核心是明确用任意长度的空格作为数值列的分隔符,先拆分变量和单位,再处理数值,最后统一清理%后缀:

library(tidyverse)

df_clean <- df %>%
  # 第一步:拆分变量与后续内容(按逗号+空格分隔)
  separate(Data, into = c("Var", "Rest"), sep = ",\\s+", extra = "merge") %>%
  # 第二步:拆分单位和所有数值列(按一个或多个空格分隔)
  separate(Rest, into = c("Unit", "Cert_Val", "ASD1", "ASD2L", "ASD2H",
                          "ASD3L", "ASD3H", "RSD1", "RSD2", "RSD3", "Low", "High"),
           sep = "\\s+", extra = "drop") %>%
  # 第三步:移除所有%后缀,转换为数值型
  mutate(across(c(Cert_Val:High), ~ as.numeric(str_remove(., "%"))))

# 查看结果结构
str(df_clean)

输出结果(数值类型正确保留小数):

'data.frame':	2 obs. of  14 variables:
 $ Var     : chr  "Ag" "Al"
 $ Method  : chr  "XRF" "XRF"
 $ Unit    : chr  "ppm" "wt.%"
 $ Cert_Val: num  0.219 5.27
 $ ASD1    : num  0.025 0.119
 $ ASD2L   : num  0.169 5.03
 $ ASD2H   : num  0.269 5.5
 $ ASD3L   : num  0.144 4.91
 $ ASD3H   : num  0.294 5.62
 $ RSD1    : num  11.48 2.25
 $ RSD2    : num  22.96 4.51
 $ RSD3    : num  34.43 6.76
 $ Low     : num  0.208 5
 $ High    : num  0.23 5.53

方案2:用tidyr::extract一次性精准匹配

通过正则表达式直接提取所有字段,避免多次拆分的繁琐,更适合结构固定的数据:

df_clean2 <- df %>%
  extract(Data,
          into = c("Var", "Unit", "Cert_Val", "ASD1", "ASD2L", "ASD2H",
                   "ASD3L", "ASD3H", "RSD1", "RSD2", "RSD3", "Low", "High"),
          regex = "^([A-Za-z]+),\\s+([\\w.%]+)\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+%)\\s+([\\d.]+%)\\s+([\\d.]+%)\\s+([\\d.]+)\\s+([\\d.]+)",
          remove = FALSE) %>%
  mutate(across(c(Cert_Val:High), ~ as.numeric(str_remove(., "%"))))

str(df_clean2)

正则表达式说明:

  • ^([A-Za-z]+):匹配开头的变量名(如Ag、Al)
  • ,\\s+([\\w.%]+):匹配逗号后的单位(兼容ppm、wt.%这类格式)
  • 后续的([\\d.]+)/([\\d.]+%):分别匹配不带%和带%的数值字段

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:35:19