【问题标题】:Extracting numbers with decimals from large strings in R从R中的大字符串中提取带小数的数字
【发布时间】:2018-10-18 13:44:48
【问题描述】:

我想从这个由 15 个观察值组成的向量中提取数字:

rs <- c("\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    4.0\n                    (1 rating)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            9 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    4.7\n                    (4 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            34 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    3.1\n                    (5 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            22 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    2.4\n                    (14 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            2,106 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    4.3\n                    (67 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            1,287 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    4.6\n                    (3 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            30 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n                \n                    \n\n    \n        New\n    \n\n\n                \n\n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    0.0\n                    (0 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            8 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n                \n                    \n\n    \n        Highest Rated\n    \n\n\n                \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    4.6\n                    (12 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            42 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    4.4\n                    (6 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            41 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    4.2\n                    (12 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            115 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    4.8\n                    (6 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            25 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    4.6\n                    (19 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            151 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    4.5\n                    (10 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            385 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    4.8\n                    (166 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            754 students enrolled\n        \n    \n\n\n    \n\n    ", 
"\n        \n            \n        \n\n        \n    \n        \n\n    \n        \n        \n            \n                \n            \n        \n        \n            \n                \n                    3.6\n                    (34 ratings)\n                \n                \n                    \n                        Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.\n                    \n                \n            \n        \n        \n    \n\n\n    \n    \n        \n\n    \n        \n            3,396 students enrolled\n        \n    \n\n\n    \n\n    "
)

如您所见,有 15 个物体很长而且很脏。但是,它们内部的模式很容易识别。每个对象由 3 个数字组成(以第一个观察为例):

  • 评级:从 0 到 5。例如,4.0
  • 评级数。例如(1 rating)
  • 已注册学生。例如9 students enrolled

我想提取所有这些数值并创建一个包含 3 列的数据框,每列用于每个变量。

我在Stackoverflow这里查了几个问题,主要集中在stringr包的gsub()的使用。但是,我找不到解决问题的关键方法。

更新

这些是我尝试过的代码:

as.numeric(str_extract(rs, "[0-9]+"))
as.numeric(str_extract(rs, "[0-9]+")[[1]])
as.numeric(str_extract(rs, "(?<=\\()[0-9]+(?=\\))"))
as.numeric(sapply(strsplit(rs, " "), "[[", 1))

【问题讨论】:

  • 如果您的输入文件有任何规律性,最好告诉我们可能是什么。
  • 所以,你检查了一些包。你能展示一些未能提供预期结果的工作吗?它可能只是一个需要调整的正则表达式。我的意思是,您当然做到了,并且不只是希望人们免费为您编写解决方案,对吧?
  • 在每个观察中都有三个数字。所以最终的输出应该是一个包含所有这些数字的三列和 15 行的数据框。我用我的一些尝试更新了这个问题。
  • aw,无论谁有两个有效的答案都是 可爱的。他们年轻的时候很可爱

标签: r regex gsub stringr


【解决方案1】:

使用来自tidyrextract,我们可以这样做:

library(dplyr)
library(tidyr)

data.frame(rs, stringsAsFactors = FALSE) %>%
  extract(rs, c("Rating", "Number_of_ratings", "Students_enrolled"),
          "(?s)(\\d\\.\\d).*?(\\d+)\\s*ratings?.*?(\\d+(?:,\\d+)?)\\s*students enrolled", 
          convert = TRUE) %>%
  mutate(Students_enrolled = as.numeric(sub(",", "", Students_enrolled)))

输出:

   Rating Number_of_ratings Students_enrolled
1     4.0                 1                 9
2     4.7                 4                34
3     3.1                 5                22
4     2.4                14              2106
5     4.3                67              1287
6     4.6                 3                30
7     0.0                 0                 8
8     4.6                12                42
9     4.4                 6                41
10    4.2                12               115
11    4.8                 6                25
12    4.6                19               151
13    4.5                10               385
14    4.8               166               754
15    3.6                34              3396

注意事项:

正则表达式看起来很复杂,但实际上并不复杂。 extract 所做的是它从每个捕获组中提取匹配项(用括号括起来的内容)并将它们变成自己的列。

  1. (?s) 是一个打开“DOTALL”模式的修饰符。这允许点 . 也匹配换行符。

  2. (\\d\\.\\d) 匹配 Rating 模式

  3. (\\d+)\\s*ratings 匹配 Number_of_ratings 模式但仅提取数字 (\\d+)

  4. (\\d+(?:,\\d+)?)\\s*students enrolled 匹配Students_enrolled 模式,但只提取“带或不带逗号的数字”模式

  5. convert = TRUE 尝试将结果列转换为其最佳数据类型,但由于Students_enrolled 中有逗号,因此需要额外的mutate 将其转换为数字

通常,如果捕获组的数量不等于输出列的数量,extract 会引发错误,但由于修饰符 (?s) 和非捕获组 (?:...) 不被视为捕获组,因此捕获组count 匹配列数。

【讨论】:

  • 感谢您的回答。但是在使用您的代码时出现错误:Error: var must evaluate to a single number or a column name, not a character vector。有什么想法吗?
  • @antecessor 糟糕,我错过了第一次将rs 存储在data.frame 中的步骤查看我的编辑
【解决方案2】:

带有注释的、可读的正则表达式的 1 依赖基础 R 解决方案。

这还展示了如何清理文本以进行处理(以您可以重复使用的方式)。

library(stringi)

do.call(
  rbind.data.frame,
  lapply(
    stri_match_all_regex(
      stri_replace_all_regex(
        stri_trim_both(rs),             # clean up outer spaces
        "[[:blank:][:space:]]+", " "    # clean up inner spaces
      ),
      "
([[:digit:]\\.]+)[[:space:]]+\\(([[:digit:],]+)[[:space:]]+rating[s]*\\)# pick up the rating and total number of ratings
[^[:digit:]]*([[:digit:],]+)[[:space:]]+student[s]*[[:space:]]+enrolled                          # pick up the number of students enrolled
",
      opts_regex = stri_opts_regex(comments = TRUE),
    ),
    function(x) {
      as.list(
        setNames(
          x[2:4], c("rating", "n_ratings", "enrolled")
        ),
        stringsAsFactors = FALSE
      )
    }
  )
)

导致:

##    rating n_ratings enrolled
## 2     4.0         1        9
## 21    4.7         4       34
## 3     3.1         5       22
## 4     2.4        14    2,106
## 5     4.3        67    1,287
## 6     4.6         3       30
## 7     0.0         0        8
## 8     4.6        12       42
## 9     4.4         6       41
## 10    4.2        12      115
## 11    4.8         6       25
## 12    4.6        19      151
## 13    4.5        10      385
## 14    4.8       166      754
## 15    3.6        34    3,396

在此之后将 ^^ 转换为 # 是非常基本的。

【讨论】:

    【解决方案3】:

    所以你的问题是它没有看到“。”作为数字的一部分,因为它在字符串中。所以你需要明确地找到数字和小数点。

    Rating <- as.numeric(str_extract(rs, "[0-9]\\.[0-9]"))
    NRatings <- str_extract(rs, "\\([0-9]") %>% str_replace("\\(","") %>% as.numeric() 
    

    我会让你根据这些例子弄清楚最后一个;)

    【讨论】:

    • 无论白痴是谁 -1'd 的答案,都会让你回到 0
    • 你也可以只对NRatings使用lookbehind:str_extract(rs, "(?&lt;=\\()[0-9]+")
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    • 2022-11-03
    相关资源
    最近更新 更多