Как найти шаблоны между наборами строк в R? - PullRequest
1 голос
/ 05 февраля 2020

Я пытаюсь найти шаблоны в наборе строк, как в следующем примере:

"2100780D001378FF01E1000000040000--------01A456000000------------"    
"3100782D001378FF03E1008100040000--------01A445800000------------"

Если я использую стандартный get_pattern из библиотеки bpa, так как он выглядит индивидуально для каждой строки, которую я получу

"9999999A999999AA99A9999999999999--------99A999999999------------"

Но моя идея состоит в том, чтобы найти что-то вроде:

"X10078XD001378FF0XE100XX00040000--------01A4XXX00000------------"

Основная цель - найти набор строк с наиболее похожим «шаблоном»

Моя первая идея состояла в том, чтобы вычислить расстояние Хемминга между ними, а затем проанализировать группы, полученные из этого расстояния, но это становится утомительным. Есть ли какой-нибудь «автоматический c» подход?

Есть идеи, как я могу выполнить sh эту миссию?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2020

Вот базовое решение R, где определена пользовательская функция findPat и применено Reduce для нахождения общего шаблона среди набора строк, т. Е.

findPat <- function(s1,s2){
  r1 <- utf8ToInt(s1)
  r2 <- utf8ToInt(s2)
  r1[bitwXor(r1,r2)!=0]<- utf8ToInt("X")
  pat <- intToUtf8(r1)
}

pat <- Reduce(findPat,list(s1,s2,s3))

, такого, что

> pat
[1] "X10078XDX0X378FF0XE100XX00040000--------01AXXXXX0000------------"

ДАННЫЕ

s1 <- "2100780D001378FF01E1000000040000--------01A456000000------------"
s2 <- "3100782D001378FF03E1008100040000--------01A445800000------------"
s3 <- "4100781D109378FF03E1008100040000--------01A784580000------------"
0 голосов
/ 05 февраля 2020

для ваших примеров данных, приведенный ниже код работает .. не знаю, как он масштабируется до производства ...

library( data.table )
#sample data
data <- data.table( name = c("2100780D001378FF01E1000000040000--------01A456000000------------",
"3100782D001378FF03E1008100040000--------01A445800000------------"))

#                                                                name
# 1: 2100780D001378FF01E1000000040000--------01A456000000------------
# 2: 3100782D001378FF03E1008100040000--------01A445800000------------


#use data.table::tstrsplit() to split the string to individual characters
l <- lapply( data.table::tstrsplit( data$name, ""), function(x) {
  #if the same character appears in all strings on the same position,return the character, else return 'X'
 if ( length( unique( x ) ) == 1 ) as.character(x[1]) else "X"
})
#paste it all together
paste0(l, collapse = "")

# [1] "X10078XD001378FF0XE100XX00040000--------01A4XXX00000------------"

небольшое объяснение

data.table::tstrsplit( data$name, "") возвращает следующий список

[[1]]
[1] "2" "3"

[[2]]
[1] "1" "1"

[[3]]
[1] "0" "0"

etc...

Используя lapply(), вы можете l oop над этим списком, определяя длину вектора с уникальными элементами. Если эта длина == 1, то во всех строках этой позиции существует один и тот же символ, поэтому верните этот символ.
Если длина> 1, то несколько символов появляются в этой возможности в разных строках и возвращают «X».

Обновление

Если вы находитесь за пределами расстояния Хэмминга, используйте stringdist -пакет

library(stringdist)
m <- stringdist::stringdistmatrix(a = data$name, b = data$name, ,method="hamming" )

#       [,1] [,2]
# [1,]    0    8
# [2,]    8    0

#to get to the minimum value for each row, exclude the diagonal first (by making it NA)
#  and the find the position with the minimum value
diag(m) <- NA
apply( m, 1, which.min )
# [1] 2 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...