【问题标题】:Convert Mixed Unit Measurements转换混合单位测量
【发布时间】:2019-02-03 09:55:43
【问题描述】:

我有一个包含大量非标准化英制和公制混合测量值的文件,我想对其进行标准化并重新发布。

该范围的示例如下所示:

df  <- data.frame(Measurements =c("1.25m", "2 Feet", "3 Inches", "5.5 cm"))

|Measurements|
|1.25m       |
|2 Feet      |
|3 Inches    |
|5.5 cm      |

我希望看起来像这样:

|Measurements|MM_Conversion|
|1.25m       |1200mm
|2 Feet      |609.6mm
|3 Inches    |76.2mm
|5.5 cm      |55mm

我不能使用measurements::conv_unitunits::set_unit,因为它们似乎都需要数字输入值。有没有一种直接的方法可以同时解析值和字符串,并进行相应的转换?

编辑 1: 遇到 Conv_Unit 无法转换 NA 值的问题。如果初始向量改为:df &lt;- data.frame(Measurements =c(NA, 1.25m", "2 Feet", "3 Inches", "5.5 cm")),您将如何绕过它?

【问题讨论】:

  • 我能想到的一种方法是创建一个自定义函数,然后使用apply 转换所有测量值
  • 也想过这个,但是因为有 20 种不同的测量值,所以它变得笨拙。

标签: r units-of-measurement unit-conversion


【解决方案1】:

它可以(很容易)完成,但您必须先修复测量中的单位,因为接受来自 measurements::conv_unit 的长度单位

# accepted units
# $length
# [1] "angstrom" "nm"       "um"       "mm"       "cm"       "dm"       "m"        "km"       "inch"     "ft"       "yd"       "fathom"   "mi"       "naut_mi" 
# [15] "au"       "light_yr" "parsec"   "point" 

所以,英寸必须变成“英寸”,而“英尺”应该变成“英尺”(执行一些正则表达式魔术;-)).. 但是......

library(tidyverse)
df  <- data.frame( Measurements =c( "1.25m", "2 ft", "3 inch", "5.5 cm" ) )

df %>% 
  #extract the numeric and the unit-parts from the string
  mutate( num_part = as.numeric( stringr::str_extract( Measurements, "\\d+\\.*\\d*" ) ), 
          unit_part = stringr::str_extract( Measurements, "[a-zA-Z]+" ) ) %>%
  #perform a rowwise operation
  rowwise() %>% 
  #convert the units to mm, row-by-row
  mutate( in_mm = conv_unit( num_part, unit_part, "mm" ) )

# Source: local data frame [4 x 4]
# Groups: <by row>
#   # A tibble: 4 x 4
#   Measurements num_part unit_part  in_mm
#   <fct>           <dbl> <chr>      <dbl>
# 1 1.25m            1.25 m         1250  
# 2 2 ft             2    ft         610. 
# 3 3 inch           3    inch        76.2
# 4 5.5 cm           5.5  cm          55  

【讨论】:

  • +1 很好地使用了rowwise,但我尽量避免使用它,因为在dplyr 的意义上它有点违反直觉。
  • @avid_user 是的,但因为 conv_unit 需要“固定”单位,我想我会在这个上偷工减料 ;-)
  • 优雅的答案,以前从未使用过rowWise。只是为了让我明白发生了什么,你能解释一下“在这里分组”的确切内容,以及“固定”单位如何影响“conv_unit”功能吗?将其注释掉,发现错误信息无济于事。
  • @rsylatian rowwise 逐行执行操作...这是必要的,因为conv_unit(x, from, to) 需要from 是一个字符串,而不是一个向量。在@avid_user 的回答中,使用map 解决了这个问题。在这种情况下,每一行(因为我设置了 rowwise() ),conv_unit 使用该特定行中的参数 x = num_partfrom = unit_part
【解决方案2】:

我们可以使用 extracttidyr 来分隔值和单位,然后使用 map2 将其输入到 conv_unit

df <- data.frame(Measurements =c(NA, "1.25m", "2 Feet", "3 Inches", "5.5 cm"))

library(tidyverse)
library(stringr)
library(measurements)

df %>%
  extract(Measurements, c("value", "unit"), 
          regex = "^([\\d.]+)\\s*([[:alpha:]]+)$", 
          remove = FALSE, convert = TRUE) %>%
  mutate(unit = str_replace_all(unit, c(Feet="ft", Inches="inch")),
         MM_Conversion = paste0(map2(value, unit, ~if(!is.na(.x)) conv_unit(.x, .y, "mm") else NA), "mm"))

结果:

  Measurements value unit MM_Conversion
1         <NA>    NA <NA>          NAmm
2        1.25m  1.25    m        1250mm
3       2 Feet  2.00   ft       609.6mm
4     3 Inches  3.00 inch        76.2mm
5       5.5 cm  5.50   cm          55mm

如果NAs 不应出现在最终输出中,则使用filter

df %>%
  extract(Measurements, c("value", "unit"), 
          regex = "^([\\d.]+)\\s*([[:alpha:]]+)$", 
          remove = FALSE, convert = TRUE) %>%
  filter(!is.na(Measurements)) %>%
  mutate(unit = str_replace_all(unit, c(Feet="ft", Inches="inch")),
         MM_Conversion = paste0(map2(value, unit, ~conv_unit(.x, .y, "mm")), "mm"))

结果:

  Measurements value unit MM_Conversion
1        1.25m  1.25    m        1250mm
2       2 Feet  2.00   ft       609.6mm
3     3 Inches  3.00 inch        76.2mm
4       5.5 cm  5.50   cm          55mm

请注意我如何手动缩写原始单位以使 conv_unit 工作。如果原始单位已经是缩写形式,那就少了一步。

【讨论】:

  • 回答也很优雅,但是 map2 函数在这里做什么?
  • conv_unit函数没有向量化,所以我们需要将value的每个元素以及对应的unit映射到conv_unit
  • 抱歉让我有点运气了,但例如说它是 Measurements = c(NA, "1.25m", "2 Feet", "3 Inches", "5.5 cm") ,答案就中断了。找到了一个非管道solution,但无法让它与您的答案一起使用。有什么办法可以将not_na &lt;- !is.na(df$Measurements) 加入其中?
  • @rsylatian 感谢您指出这一点。您希望任何NA 行保留NA,还是直接删除?
  • @rsylatian 查看我的更新。它现在应该与 NA 值一起使用。如果您想从输出中删除它们,还有另一个修复方法。
猜你喜欢
  • 1970-01-01
  • 2012-02-06
  • 2013-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-20
  • 2020-10-14
  • 1970-01-01
相关资源
最近更新 更多