简体   繁体   中英

Convert a string into a similarity matrix

I have number of strings in an idiosyncratic format, representing sets. In R, I'd like to convert them into a similarity matrix.

For example, a string showing that 1+2 comprise a set, 3 is alone in a set, and 4,5, and 6 comprise a set is:

"1+2,3,4+5+6"

For the example above, I'd like to be able to produce

  [,1] [,2] [,3] [,4] [,5] [,6] [1,] 1 1 0 0 0 0 [2,] 1 1 0 0 0 0 [3,] 0 0 1 0 0 0 [4,] 0 0 0 1 1 1 [5,] 0 0 0 1 1 1 [6,] 0 0 0 1 1 1 

It seems like this should be a painfully simple task. How would I go about it?

Here's an approach:

out <- lapply(unlist(strsplit("1+2,3,4+5+6", ",")), function(x) {
    as.numeric(unlist(strsplit(x, "\\+")))
})

x <- table(unlist(out), rep(seq_along(out), sapply(out, length)))

matrix(x %*% t(x), nrow(x))

##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    1    0    0    0    0
## [2,]    1    1    0    0    0    0
## [3,]    0    0    1    0    0    0
## [4,]    0    0    0    1    1    1
## [5,]    0    0    0    1    1    1
## [6,]    0    0    0    1    1    1

Pseudocode:

Split at , to get an array of strings, each describing a set.
For each element of the array:
    Split at + to get an array of set members
    Mark every possible pairing of members of this set on the matrix

You can create a matrix in R with:

m = mat.or.vec(6, 6)

By default, the matrix should initialize with all entries 0. You can assign new values with:

m[2,3] = 1

Here's another approach:

# write a simple function
similarity <- function(string){
  sets <- gsub("\\+", ":", strsplit(string, ",")[[1]])
  n <- as.numeric(tail(strsplit(gsub("[[:punct:]]", "", string), "")[[1]], 1))
  mat <- mat.or.vec(n, n)
  ind <- suppressWarnings(lapply(sets, function(x) eval(parse(text=x))))

  for(i in 1:length(ind)){
    mat[ind[[i]], ind[[i]]] <- 1
  } 

  return(mat)

}

# Use that function
> similarity("1+2,3,4+5+6")
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    1    0    0    0    0
[2,]    1    1    0    0    0    0
[3,]    0    0    1    0    0    0
[4,]    0    0    0    1    1    1
[5,]    0    0    0    1    1    1
[6,]    0    0    0    1    1    1

# Using other string
> similarity("1+2,3,5+6+7, 8")
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    1    1    0    0    0    0    0    0
[2,]    1    1    0    0    0    0    0    0
[3,]    0    0    1    0    0    0    0    0
[4,]    0    0    0    0    0    0    0    0
[5,]    0    0    0    0    1    1    1    0
[6,]    0    0    0    0    1    1    1    0
[7,]    0    0    0    0    1    1    1    0
[8,]    0    0    0    0    0    0    0    1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM