需要使用 R 从字符串列中提取单个字符

2024-01-13

背景

下面是我的gamedatadput 形式的数据集——它包含一些 MLB 比赛的比分。

structure(list(team = c("NYM", "NYM", "BOS", "NYM", "BOS"), linescore = c("010000000", 
"(10)1140006x", "002200010", "00000(11)01x", "311200"), ondate = structure(c(18475, 
18476, 18487, 18489, 18494), class = "Date")), class = "data.frame", row.names = c(NA, 
-5L))

例如,这是一行分数:“002200010”。

有些线分数以“x”结尾,有些线分数在括号中包含两位数,如“00000(11)01x”。括号内的每个数字表示该队在该局中得了多少分。如果一支球队在一局中得分超过 9 分,则该数字放在括号中,因此在得分线“00000(11)01x”中,球队在第六局中得分 11 分,并且在下半局没有击球。第九个(用“x”表示)。

并非每条线得分都有九局。有些有更多,有些只有六个。

我需要做什么

First,我需要做的是获取一支球队在每局中得分多少分,例如第一,第二,第三等,并将每个得分在新专栏中。我更喜欢使用 dplyr 的解决方案。

我已经查看了 stackoverflow 的建议解决方案,但没有发现符合我需要的解决方案。如果有的话,如果您能分享它的 URL,我将不胜感激。

我尝试使用以下代码来做到这一点:

gamedata %>%
  select(ondate, team, linescore) %>%
  mutate(inng1 = str_extract(linescore, "\\d|\\(\\d{2}\\)"))

这是输出:

ondate      team linescore    inng1
2020-08-01  NYM 010000000       0   
2020-08-02  NYM (10)1140006x  (10)  
2020-08-13  BOS 002200010       0   
2020-08-15  NYM 00000(11)01x    0   
2020-08-20  BOS 311200          3

Second,我怎样才能删除其中的括号inng1“10”列?

下面的代码产生了下面的错误:

gamedata %>%
  select(ondate, team, linescore) %>%
  mutate(inng1 = str_extract(linescore, "\\d|\\(\\d{2}\\)"))
 str_remove_all(inng1,"[()]")

这是我收到的错误消息:

“stri_replace_all_regex(字符串、模式、fix_replacement(替换)中出现错误:找不到对象‘inng1’”

Third,我需要知道如何提取每个附加局的得分,从第二局开始,将每个值放入其自己的列中,例如 inng2、inng3 等。

最后,我应该得到上面显示的输出(每个两位数局没有括号),每个局有一列,所以会有一个标题为“inng1”、“inng2”、“inng3”、“inng4”的列,局列中的数据需要是数字,稍后我将对它们进行求和。


解决方案02

这是您可以用于解决此问题的另一种解决方案,该解决方案比第一个解决方案更有效,并且主要基于purrr函数族:

library(dplyr)
library(purrr)

df %>%
  bind_cols(
    map(df %>% select(linescore), ~ strsplit(.x, "\\(|\\)")) %>%
      flatten() %>%
      map_dfr(~ map(.x, ~ if(nchar(.x) > 2) strsplit(.x, "")[[1]] else .x) %>%
                reduce(~ c(.x, .y)) %>%
                keep(~ nchar(.x) != 0) %>% t() %>%
                as_tibble() %>% 
                set_names(~ paste0("inng", 1:length(.x)))) %>%
      mutate(across(everything(), ~ replace(.x, .x == "x", NA_character_)), 
             count_inng = pmap_dbl(cur_data(), ~ sum(!is.na(c(...)))), 
             sums_inng = pmap_dbl(select(cur_data(), starts_with("inng")), 
                                  ~ sum(as.numeric(c(...)), na.rm = TRUE)))
  )

  team    linescore     ondate inng1 inng2 inng3 inng4 inng5 inng6 inng7 inng8 inng9 count_inng
1  NYM    010000000 2020-08-01     0     1     0     0     0     0     0     0     0          9
2  NYM (10)1140006x 2020-08-02    10     1     1     4     0     0     0     6  <NA>          8
3  BOS    002200010 2020-08-13     0     0     2     2     0     0     0     1     0          9
4  NYM 00000(11)01x 2020-08-15     0     0     0     0     0    11     0     1  <NA>          8
5  BOS       311200 2020-08-20     3     1     1     2     0     0  <NA>  <NA>  <NA>          6
  sums_inng
1         1
2        22
3         5
4        12
5         7

解决方案01

我对我的解决方案进行了一些修改,因为它错误地替换了输出向量中的两位数,我认为它已得到修复。 我认为这个解决方案可能对您有帮助。为此,我决定编写一个自定义函数来检测两位数字并修剪分数的输出:

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

fn <- function(x) {
  out <- c()
  if(str_detect(x, "\\((\\d){2}\\)")) {
    double <- str_replace_all(str_extract(x, "\\((\\d){2}\\)"), "[)()]", "")
    ind <- str_locate(x, "\\(")
    x <- str_remove(x, "\\((\\d){2}\\)")
    out <- c(out, str_split(x, "")[[1]])
    out[(ind[1, 1]+1):(length(out)+1)] <- out[(ind[1, 1]):length(out)]
    out[ind] <- double
  } else {
    out <- c(out, str_split(x, "")[[1]])
  }
  if(any(grepl(")", out))) {
    out <- out[-which(out == ")")]
  }
  out
}

# Test
fn("(10)1140006x)")
[1] "10" "1"  "1"  "4"  "0"  "0"  "0"  "6"  "x" 

然后我们以逐行操作将其应用到数据集上:

df %>%
  mutate(linescore = map(linescore, fn)) %>% 
  unnest_wider(linescore) %>%
  rename_with(~ gsub("(\\.\\.\\.)(\\d)", paste0("inng", "\\2"), .), starts_with("...")) %>%
  mutate(across(starts_with("inng"), ~ {replace(.x, .x == "x", NA)
    as.numeric(.x)}), 
    inns_count = pmap_dbl(select(cur_data(), starts_with("inng")), 
                          ~ sum(!is.na(c(...)))), 
    inns_sums = pmap_dbl(select(cur_data(), starts_with("inng")), 
                         ~ sum(c(...), na.rm = TRUE)))

# A tibble: 5 x 13
  team  inng1 inng2 inng3 inng4 inng5 inng6 inng7 inng8 inng9 ondate     inns_count inns_sums
  <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <date>          <dbl>     <dbl>
1 NYM       0     1     0     0     0     0     0     0     0 2020-08-01          9         1
2 NYM      10     1     1     4     0     0     0     6    NA 2020-08-02          8        22
3 BOS       0     0     2     2     0     0     0     1     0 2020-08-13          9         5
4 NYM       0     0     0     0     0    11     0     1    NA 2020-08-15          8        12
5 BOS       3     1     1     2     0     0    NA    NA    NA 2020-08-20          6         7
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

需要使用 R 从字符串列中提取单个字符 的相关文章

随机推荐

  • round() 和 trunc() 函数有什么区别?

    我对这些功能很困惑 在数学中 rounding http en wikipedia org wiki Rounding表示四舍五入到最接近的整数 因此四舍五入 3 4 的结果是 3 四舍五入 3 6 的结果是 4 Truncating ht
  • Crystal Reports 使用 13.0.2000 的哪个版本?

    我的任务是对几年前编写的 ASP NET Web Forms 应用程序进行一些小的更改 该应用程序的实现者已经不在我们身边 几年前就离开了 该应用程序中有 6 个报告 所有报告都使用某些版本的 Crystal Reports 当我看着Web
  • 如何使用 Eloquent 查询两个坐标之间的距离

    我知道这个问题已经被问过很多次了 但我没想到要根据我的需要来制作 我需要查询距离另一个用户最近的用户 基本上 我有一个users表 这个表有一个one to one与的关系users locations具有纬度和经度字段的表 所以我看过这个
  • 是否可以一步在堆上创建 lambda? [复制]

    这个问题在这里已经有答案了 我们可以像这样创建一个 lambda auto x 我可以在堆上创建一个副本 如下所示 auto y new decltype x x 问题是 是否可以一步完成此操作 在堆上创建 lambda 而不需要额外的步骤
  • 我可以阻止 JDialog 在按下退出/输入键时关闭吗?

    我创建了一个对话框来接受用户击键来更改菜单项的键绑定 我希望 Enter 和 escape 成为用户可以绑定的键 但它们都会关闭对话框 如何拦截这些压力机 编辑 对话框是使用 JOptionPane 和自定义组件创建的 GetKeyComp
  • 初始化全局变量类

    对于这样一个基本问题表示歉意 但我无法弄清楚 我知道你可以像这样初始化一个类 QFile file C example 但是如何从全局变量初始化它呢 例如 QFile file QFile class int main file need
  • 有没有办法仅通过国家/地区名称获取时区? [复制]

    这个问题在这里已经有答案了 您好 我知道这个问题被问了很多次 但这些问题与网络服务有关 我正在开发一个应用程序 显示用户选择国家 地区的时区 例如 我有所有国家 地区的列表 当用户从中选择一个国家 地区时 我想按国家 地区名称 可能是字符串
  • Python Facebook API - 光标分页

    我的问题涉及学习如何使用 Facebook 的 Python API 检索我的整个好友列表 当前结果返回一个具有有限数量好友的对象以及指向 下一页 的链接 我如何使用它来获取下一组朋友 请发布可能重复的链接 任何帮助将不胜感激 一般来说 我
  • Linux 中的 -emit-llvm

    我是 LLVM 的新手 尝试在 Linux 上生成人类可读的 ll 文件 我安装了 llvm gcc 但据我所知它只能生成汇编代码 S 选项 有什么办法可以得到类似于 llvm 在线生成的东西compiler http llvm org d
  • 使用 IIS 以纯文本形式提供不带扩展名的文件

    我尝试过使用来自的答案IIS 如何提供没有扩展名的文件 https stackoverflow com questions 19950882 iis how to serve a file without extension
  • 对象引用和对象哈希码之间的区别

    java中对象的引用和同一对象的哈希码值有什么区别 它们是完全不同的两个概念 Cat oldCat new Cat Cat newCat new Cat Cat oldCatRef oldCat 在上面的例子中 oldCat and old
  • 在 SQL 输出中插入双引号

    例如 在运行查询并查看输出后 select from People 我的输出如下 First Last Email Ray Smith email protected cdn cgi l email protection 我如何导出这些数据
  • 如何使用 JavaScript 检查文件是否存在?

    如何使用 JavaScript 检查文件是否存在 在本例中我想检查的是 xml 文件 如果您使用的是 jQuery 您可以尝试加载该文件 ajax type GET url some xml success function found e
  • 如何强制 pytest 写入颜色输出?

    即使在写入管道时 如何强制 pytest 以颜色显示结果 似乎没有任何命令行选项可以执行此操作 从 2 5 0 开始 py test 有这个选项 color yes 从 2 7 0 开始 还应该可以执行以下操作 export PYTEST
  • Spring 与 JSF 2 的比较 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何两两比较多次测量的增减?

    我有一个数据 我想通过取差值来两两比较测量值 如果差值大于 0 2 则添加另一列为 是 否则为 否 就像图像中的示例数据一样 并且 在每个人的最后 如果至少有一个 是 则最终结果为 是 我已手动填写第一行 但我想对我的所有个人 1000 个
  • Python 并删除列表列表中的重复项,无论列表中的顺序如何

    我已经搜索过 但没有找到与我相同的问题 我想从 python 中的列表列表中删除重复项 但是 我不在乎列表中值的顺序 我目前的做法太耗时了 我想做的事 A 1 2 3 2 3 4 3 4 5 3 2 4 我想搜索 A 并删除所有重复项 这里
  • 使用python同时向多个CC和多个TO收件人发送电子邮件

    分别尝试了多个 to 和多个 cc 效果很好 但是当我尝试两者时 出现错误 File 路径 Continuum anaconda2 envs mypython lib smtplib py 第 870 行 在 sendmail sender
  • std::string 用 bool 初始化

    考虑以下初始化 std string falseString false std string trueString true With g 5 2 0 编译器会抛出警告falseString 而错误为trueString With cla
  • 需要使用 R 从字符串列中提取单个字符

    背景 下面是我的gamedatadput 形式的数据集 它包含一些 MLB 比赛的比分 structure list team c NYM NYM BOS NYM BOS linescore c 010000000 10 1140006x