在 R 中识别字母数字字符串中的序列

Identify sequences in alphanumeric strings in R

提问人:coult 提问时间:8/21/2023 最后编辑:Markcoult 更新时间:8/22/2023 访问量:68

问:

我正在尝试为交易 ID 是连续的时创建一个标志。由于我不会在这里讨论的原因,这些可能是一个危险信号。我遇到的问题是 ID 没有标准化。有些只能是数字,有些是字母数字。我想确定供应商的交易是连续的 X 个交易(连续多少个待定)交易的情况。数据将按供应商分组,我想提取存在序列的实例的所有行和列。下面是一个简化得多的例子:

df <- read.table(text=
"Vendor        'Transaction ID'
 ACME               1
 ACME               2
 ACME               3
 JDOE               A1
 JDOE               A6
 JDOE               A10
 XYZ                B12
 XYZ                B13
 XYZ                B14", header=TRUE)

在本例中,我想提取所有 ACME 和所有 XYZ 行的供应商和事务 ID,因为它们是按顺序排列的。我做了一些研究,但没有找到一种似乎适合我正在尝试的方法。

R 数据帧 序列 信息提取识别

评论


答:

1赞 Mark 8/21/2023 #1

我的早期版本使用了 stringr 和 as.numeric,但我真的很喜欢 Andrew 回答中的函数,所以我无情地窃取了它 ^_^parse_number()

library(tidyverse)

df %>%
  filter(Transaction.ID %>% 
          parse_number() %>%
          diff() %>%
          {all(. == 1)}, .by = Vendor)
4赞 AndrewGB 8/21/2023 #2

一种选择是使用 将 转换为数字,然后您可以为每个组中的连续值创建分组列。然后,您可以根据您想要拥有的连续数字数量。在这里,我使用大于 1,但您可以根据所需的条件更新语句。然后,我取消分组并删除多余的列 - 和 .Transaction_IDparse_numberfilterfilterTransaction_ID2grp

library(dplyr)
library(readr)

df %>%
  mutate(Transaction_ID2 = parse_number(Transaction_ID)) %>%
  group_by(Vendor, grp = cumsum(c(1, diff(Transaction_ID2) != 1))) %>%
  filter(n() > 1) %>% 
  ungroup %>% 
  select(-c(Transaction_ID2, grp))

输出

  Vendor Transaction_ID
  <chr>  <chr>         
1 ACME   1             
2 ACME   2             
3 ACME   3             
4 XYZ    B12           
5 XYZ    B13           
6 XYZ    B14   
1赞 jpsmith 8/21/2023 #3

包更优雅,但为了更好地衡量,基本的 R 方法是在按组查找序列号后创建一个布尔值,然后 [索引]:tapply

xx <- tapply(df$Transaction.ID, df$Vendor, function(x) 
  length(rle(diff(as.numeric(gsub("[A-Za-z]", '\\1', x))))$lengths) == 1)

# ACME  JDOE   XYZ 
# TRUE FALSE  TRUE 

df[df$Vendor %in% names(xx[xx]),]

#  Vendor Transaction.ID
#1   ACME              1
#2   ACME              2
#3   ACME              3
#7    XYZ            B12
#8    XYZ            B13
#9    XYZ            B14