【问题标题】:Count specific value up to a position in a string for each row (R)将特定值计数到每行的字符串中的某个位置 (R)
【发布时间】:2020-05-13 20:29:30
【问题描述】:

我有一个如下的数据框:

ID   | Provider | String
-----------------------
1    | A        | A, NA, NA, B, NA
2    | B        | NA, A, B, NA, NA, NA
3    | B        | B
4    | C        | C, NA, NA, A, NA, NA, C, NA

我想计算字符串中匹配“提供者”列中的值到不匹配值或末尾的值之后的 NA。

想要的输出是

   ID    | Provider  | String                     | Output
    ------------------------------------------------------
    1    | A        | A, NA, NA, B, NA            | 2 
    2    | B        | NA, A, B, NA, NA, NA        | 3
    3    | B        | B                           | 0
    4    | C        | C, NA, NA, A, NA, NA, C, NA | 3

ID1 有一个提供者 A,并且字符串在 A 之后遇到 B 之前有两个 NA。 ID2 有一个提供者 B,字符串在 B 之后有三个 NA。 ID3 有一个提供者 B 并且字符串在 B 之后没有 NA。 ID4 有一个提供者 C,字符串在 C 之后有两个 NA,然后再遇到 A + 在第二个 C 之后再有一个 NA。

我最初的方法是先使用分词器计算总 NA

df$Output0 <- sapply(df$String, function(x) sum(unlist(tokenize_words(x)) %in% c('NA')))

但是,它返回全 0。

我应该如何解决以下问题?

【问题讨论】:

  • 请使用dput(df) 的输出编辑问题。或者,如果 dput(head(df, 20)) 的输出太大。

标签: r


【解决方案1】:

一个使用正则表达式的选项和来自 stringr 的两个函数。

library("data.table")
library("stringr")

DT <- data.table(
  ID = 1:3,
  Provider = c("A", "B", "C"),
  String = c("A, NA, NA, B, NA", "NA, A, B, NA, NA, NA", "C, NA, NA, A, NA, NA, C, NA")
)

DT[, Output := sum(str_count(
  str_extract_all(String, paste0(Provider, "(, NA)*"), simplify = TRUE),
  "NA")), 
  by = ID
]

DT
   ID Provider                      String Output
1:  1        A            A, NA, NA, B, NA      2
2:  2        B        NA, A, B, NA, NA, NA      3
3:  3        C C, NA, NA, A, NA, NA, C, NA      3

【讨论】:

  • 谢谢。上面代码中的“simplify = TRUE”是如何工作的?
  • 'str_extract_all' 将返回一个结果列表,而不是一个向量,如果你不添加它。
【解决方案2】:

这是使用regmatches + gregexpr 的基本 R 解决方案

df$Output0 <- apply(
    df,
    1,
    function(x) sum(unlist(gregexpr("NA", toString(unlist(regmatches(x[3], gregexpr(sprintf("%s(, NA)+", x[2]), x[3])))))) > 0)
)

这样

> df
  ID Provider                      String Output0
1  1        A            A, NA, NA, B, NA       2
2  2        B        NA, A, B, NA, NA, NA       3
3  3        B                           B       0
4  4        C C, NA, NA, A, NA, NA, C, NA       3

数据

df <- 
structure(list(ID = 1:4, Provider = c("A", "B", "B", "C"), String = c("A, NA, NA, B, NA",
"NA, A, B, NA, NA, NA", "B", "C, NA, NA, A, NA, NA, C, NA")), class = "data.frame", 
row.names = c(NA,
-4L))

【讨论】:

  • 谢谢。这很有帮助。我有一个小问题。为什么第一个代码最后需要“0”?
  • @duyzero123 这是因为gregexpr如果没有找到匹配的模式会返回0&gt;0 可以将其解释为在逻辑值方面找到的匹配模式
猜你喜欢
  • 2016-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 2016-02-15
  • 1970-01-01
相关资源
最近更新 更多