【问题标题】:Extract numeric values from strings and split them according to original order从字符串中提取数值并按照原始顺序拆分它们
【发布时间】:2019-09-26 10:22:54
【问题描述】:

我正在尝试从 R 中包含数值和非数值的字符串列中提取所有数值。我的目标是通过用逗号替换所有非数字值的累积来保持原始顺序。

我的示例数据:

name <- c("./Stimuli\49stim_9_with_14_vs_23_mix2.png", "./Stimuli\54stim_14_with_15_vs_21_mix2.png", "./Stimuli\75stim_15_with_18_vs_26_incongruent.png")

我的预期结果:

expectedpoutcome <- c("49, 9, 14, 23, 2", "54, 14, 15, 21, 2", "75, 15, 18, 26")

我能得到的最接近的:

library(stringr)

myoutcome <- name %>% str_match_all("[0-9]+") %>% unlist %>% as.numeric

该列表的问题在于有关数字来自哪个原始字符串的信息丢失了。

【问题讨论】:

  • 你说你尝试过使用正则表达式。请向我们展示您的尝试。然后我们可以提供具体的更正。另外,文件名中的这些反斜杠是从哪里来的?他们几乎肯定不应该在那里。
  • @KonradRudolph 我已经编辑了帖子并删除了正则表达式,因为它是错误的术语。

标签: r dplyr stringr


【解决方案1】:

您的正则表达式是正确的。相反,问题在于它之后的代码:您正在展平列表(因此丢失了数字和原始字符串之间的对应关系),然后您将输出转换为数字,即使您表示要获取一个字符串

所以,首先删除%&gt;% unlist %&gt;% as.numeric 步骤。

接下来,有一个巧妙的技巧可以将字符串列表合并为一个以逗号分隔的字符串:toString。因此,将其应用于您的结果列表:

name %>% stringr::str_match_all("[0-9]+") %>% sapply(toString)

我们有它。

另外你可以简化正则表达式:\d 等同于[0-9];给我们:

name %>% stringr::str_match_all("\\d+") %>% sapply(toString)

最后,你的“预期结果”是完全错误的,因为你误解了字符串中反斜杠转义序列的含义。 Read the documentation on string escape sequences.

或者,您可以执行相反的操作,而不是匹配所有数字:匹配所有不是数字的内容,并将此类运行替换为', '。但是,之后您需要删除前导和尾随逗号:

trimws(gsub('\\D+', ', ', name), whitespace = ', ')

【讨论】:

  • Danke,你是对的,将结果保存在字符串中是错误的目标,也不利于我的最终目标,即以某种方式将数字“扩展”到不同的列第一个数字有一列,第二个数字有一列,依此类推......你能帮我吗?
  • @psyph 如果每个字符串中的数字计数相同,您可以将上面的sapply(toString) 替换为lapply(as.vector) %&gt;% {do.call(rbind.data.frame, .)}。然后你只需要清理自动生成的列名。 通常最后丑陋的{do.call(rbind.data.frame, .)} 位可以被dplyr 的bind_rows 替换,但由于某种原因,这不适用于我安装的dplyr 版本,可能是由于一个错误。
  • 遗憾的是,有些字符串包含四个数字和一些五个。有没有办法为所有具有 4 个数字的值字符串创建第五列并获取 NA?
  • 但是如果您为了它而对它不感兴趣,我已经可以使用您刚刚提供的解决方案。非常感谢。
【解决方案2】:

一个 tidyverse 的解决方案是这样的:

name %>% str_extract_all("\\d+") %>% map_chr(paste, collapse = ", ")

这不会产生您显示的输出,原因是您提供的转义字符最终根本不是数字。
R 不会知道按原样提供的内容以及通过转义序列提供的内容。

【讨论】:

    【解决方案3】:

    使用基数 R,我们可以提取所有使用 gregexprregmatches 的数值,并使用 toString 将它们更改为逗号分隔的字符串。

    sapply(regmatches(name, gregexpr("[0-9]+", name)), toString)
    #[1] "49, 9, 14, 23, 2" "14, 15, 21, 2"    "75, 15, 18, 26"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-30
      • 2020-06-15
      • 1970-01-01
      • 1970-01-01
      • 2022-12-21
      • 2021-06-23
      • 2020-05-29
      • 1970-01-01
      相关资源
      最近更新 更多