如何在数据中找到相同的字符串

时间:2018-01-08 21:35:36

标签: r string

我有这样的数据

df<- structure(list(df1 = structure(1:7, .Label = c("A0A023J5X5", 
"A0A023J5X7", "A0A023J5Y1", "A0A023J5Y8", "A0A023J5Z0", "A0A023J601", 
"A0A023J609"), class = "factor"), df2 = structure(1:7, .Label = c("A0A023J5X5", 
"A0A023J5X7", "A0A023J5Y1", "A0A023J5Y8", "A0A023J5Z0", "A0A023J601", 
"A0A023J609"), class = "factor"), df3 = structure(c(2L, 3L, 4L, 
1L, 1L, 1L, 1L), .Label = c("", "A0A023J5X5", "A0A023J5X7", "A0A023J5Y1"
), class = "factor"), df4 = structure(c(4L, 3L, 5L, 1L, 2L, 6L, 
7L), .Label = c("A0A023J5Y8", "D3Z2H7", "O35945", "Q6ZPS9", "Q7TMW3", 
"Q925B0-1", "Q9EPC1"), class = "factor"), df5 = structure(c(5L, 
4L, 6L, 2L, 3L, 1L, 1L), .Label = c("", "A0A023J601", "A0A023J609", 
"O35945", "Q6ZPS9", "Q7TMW3"), class = "factor")), .Names = c("df1", 
"df2", "df3", "df4", "df5"), class = "data.frame", row.names = c(NA, 
-7L))

我想找到每列中相同字符串的数量

所以像这样的输出就是我要找的东西

    df1 df2 df3 df4 df5
df1 7   7   3   1   2
df2 7   7   3   1   2
df3 3   3   3   0   0
df4 1   1   0   7   3
df5 2   2   0   3   5

例如,第1列,有7个字符串,与df2列相同,因此它将得到7

4 个答案:

答案 0 :(得分:2)

这里有一些用于循环的东西,因此大数据可能会很慢。它必须应对&#34;&#34;在原始数据中。

dimension = ncol(df)
result = matrix(data=0, nrow = dimension, ncol = dimension)
for (row in 1:dimension) {
  for (col in 1:dimension) {
    intersection = intersect(df[,row], df[,col])
    # work round the "" in the data
    intersection = intersection[!intersection == ""]
    result[row,col] = length(intersection)
  }
}
result.df = data.frame(result)
names(result.df) = names(df)
row.names(result.df) = names(df)
result.df

#    df1 df2 df3 df4 df5
#df1   7   7   3   1   2
#df2   7   7   3   1   2
#df3   3   3   3   0   0
#df4   1   1   0   7   3
#df5   2   2   0   3   5

答案 1 :(得分:2)

另一种没有循环的解决方案,并使用外部产品比较将矩阵的每个元素与所有其他元素进行比较

1)您似乎将空字符串视为NA

df[df == ""] <- NA

2)使用outer函数将矩阵的每个元素与所有其他元素进行比较。由于lapply

,我一次只做一列
tmp <- lapply(df,  function(x) outer(x, t(df), FUN = "=="))

3)求和以获得每个向量的匹配数

tmp <- lapply(tmp, function(x) apply(x, 2, sum, na.rm = T))

4)将每个向量粘贴到矩阵

do.call(rbind, tmp)

   ##     df1 df2 df3 df4 df5
   ## df1   7   7   3   1   2
   ## df2   7   7   3   1   2
   ## df3   3   3   3   0   0
   ## df4   1   1   0   7   3
   ## df5   2   2   0   3   5

答案 2 :(得分:0)

始终从概念化问题开始。这里有两个不同的步骤:

  1. 生成列之间唯一对的所有可能组合
  2. 查找唯一匹配的数量(或应用您选择的任何特殊比较算法)
  3. 组合

    让自己回到高中时期的组合和排列。我们希望开发列对的所有组合,其中顺序无关紧要。幸运的是,有一个函数combn可以做到这一点。让我们干净并使用df

    > combn(dim(df)[2], 2)
    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    [1,]    1    1    1    1    2    2    2    3    3     4
    [2,]    2    3    4    5    3    4    5    4    5     5
    > combn(names(df), 2)
         [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9]  [,10]
    [1,] "df1" "df1" "df1" "df1" "df2" "df2" "df2" "df3" "df3" "df4"
    [2,] "df2" "df3" "df4" "df5" "df3" "df4" "df5" "df4" "df5" "df5"
    

    使用转置函数t生成数据框。我为你的例子保留了这个亮点,除了使用确切的列名称这一点很简单。

    df1 <- data.frame(t(combn(5,2)))
    names(df1) <- c("first", "second")
    

    匹配功能

    根据您的示例,我发现简单的%in%运算符足以满足您的解决方案。看看这个例子:

    > sum(df$df1 %in% df$df5)
    [1] 2
    

    我使用sapply函数生成所有匹配的简单向量。我取df1数据框并使用第一列和第二列作为原始数据框df的列索引,然后进行逐列比较。

    df1$match <- sapply(1:dim(df1)[1], function(x) {
    
     sum(df[,df1[x,1]] %in% df[,df1[x,2]])
    
    })
    

    查看输出以确认它是正确的:

    > df1
       first second match
    1      1      2     7
    2      1      3     3
    3      1      4     1
    4      1      5     2
    5      2      3     3
    6      2      4     1
    7      2      5     2
    8      3      4     0
    9      3      5     4
    10     4      5     3
    

    这听起来很花哨,但事实上,一旦你将问题分解为两个步骤,它就会很简单。在将来尝试这样做,您将走向良好的编程实践。

答案 3 :(得分:0)

加载数据并将列(df1:df5)转换为唯一列,然后将其转换为一个因子以获取数值而不是字符串:

library(dplyr)
mydf_chr <- mydf %>% 
    mutate_all(.funs=as.character()) %>%
    mutate_all(.funs=funs(gsub(pattern="^$",replacement="NA",x=.))) %>% 
    gather(Your_string) %>% 
    mutate(value=as.factor(value))

然后,您可以使用唯一因子的数字级别重新创建数据框,以识别df1:df5列中的哪个元素相同(不相似...)

Strings <- mydf_chr$value
Numeric_strings <- as.numeric(Strings)
YourDf <- as.data.frame(matrix(Numeric_strings,nrow=7,ncol=5))
names(YourDf) <- c(paste0("df",1:5))

您将获得以下结果:

  df1 df2 df3 df4 df5
1   1   1   1  11  11
2   2   2   2  10  10
3   3   3   3  12  12
4   4   4   9   4   6
5   5   5   9   8   7
6   6   6   9  13   9
7   7   7   9  14   9

这意味着,对于istance,第4行有3个相同的字符串,如数据框中所示:

  df1        df2        df3        df4        df5
4 A0A023J5Y8 A0A023J5Y8            A0A023J5Y8 A0A023J601