для ваших примеров данных, приведенный ниже код работает .. не знаю, как он масштабируется до производства ...
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