【问题标题】:merging and counting similar strings合并和计算相似的字符串
【发布时间】:2017-04-26 06:25:42
【问题描述】:

我有一个包含三列的数据,例如

Inputdf<-structure(list(df1 = structure(c(4L, 5L, 2L, 1L, 3L), .Label = c("P61160,P61158,O15143,O15144,O15145,P59998,O15511", 
"P78537,Q6QNY1,Q6QNY0", "Q06323,Q9UL46", "Q92793,Q09472,Q9Y6Q9,Q92831", 
"Q92828,Q13227,O15379,O75376,O60907,Q9BZK7"), class = "factor"), 
    df2 = structure(c(3L, 2L, 5L, 4L, 1L), .Label = c("", "P61158,O15143,O15144", 
    "Q06323,Q9UL46", "Q6QNY0", "Q92828"), class = "factor"), 
    df3 = structure(c(5L, 4L, 3L, 2L, 1L), .Label = c("", "O15511", 
    "Q06323,Q9UL46", "Q6QNY0", "Q92793,Q09472"), class = "factor")), .Names = c("df1", 
"df2", "df3"), class = "data.frame", row.names = c(NA, -5L))

例如,我正在尝试在此数据中查找类似的字符串

df1,我有第一行我有Q92793,Q09472,Q9Y6Q9,Q92831 然后我查看 df2 和 df3 并查看其中是否有任何这些成员,然后在此示例中,我制作以下数据

df1 df2 df3 Numberdf1      df2     df3
1   0   1   4              0      Q92793,Q09472

df1 1 表示 df1 的第一行 df2 0 表示没有任何相似性 df3 1,表示df3的第一行与df1的第1行相似 Numberdf1,它是由,分隔的字符串的计数,即4 df2 为 0,因为没有任何类似的字符串符合 df2 df3 是 Q92793,Q09472 在这里粘贴相似的字符串

一个愿望输出如下所示

out<- structure(list(df1 = 1:5, df2 = c(0L, 3L, 4L, 2L, 1L), df3 = c(1L, 
0L, 2L, 4L, 3L), Numberdf1 = c(4L, 6L, 2L, 7L, 2L), df2.1 = structure(c(1L, 
5L, 4L, 2L, 3L), .Label = c("0", "P61158,O15143,O15144", "Q06323,Q9UL46", 
"Q6QNY0", "Q92828"), class = "factor"), df3.1 = structure(c(5L, 
1L, 4L, 2L, 3L), .Label = c("0", "O15511", "Q06323,Q9UL46", "Q6QNY0", 
"Q92793,Q09472"), class = "factor")), .Names = c("df1", "df2", 
"df3", "Numberdf1", "df2.1", "df3.1"), class = "data.frame", row.names = c(NA, 
-5L))

下面的函数不起作用,例如使用这个数据作为输入

Inputdf1<- structure(list(df1 = structure(c(2L, 3L, 1L), .Label = c("Q06323,Q9UL46", 
"Q92793,Q09472,Q9Y6Q9,Q92831", "Q92828,Q13227,O15379,O75376,O60907,Q9BZK7"
), class = "factor"), df2 = structure(1:3, .Label = c("P25788,P25789", 
"Q92828, O60907, O75376", "Q9UL46, Q06323"), class = "factor"), 
    df3 = structure(c(2L, 1L, 3L), .Label = c("Q92831, Q92793, Q09472", 
    "Q9BZK7, Q92828, O75376, O60907", "Q9UL46, Q06323"), class = "factor")), .Names = c("df1", 
"df2", "df3"), class = "data.frame", row.names = c(NA, -3L))

【问题讨论】:

  • 你能检查一下out吗?这些值是否正确?在out 的第二行中,当df2 的值为P61158,O15143,O15144 时,你是如何得到df2.1 为Q92828 的,最后一行也是如此
  • @akrun df1 的行很重要,它可能与 df2 的第 2 行或第 3 行或第 10 行相似。在这种情况下,df1 的第二行在 df2 的第三行有一个类似的字符串。现在清楚了吗?

标签: r string


【解决方案1】:

这适用于您的示例:

# First convert factors to strings to lists
Inputdf[] = lapply(Inputdf, as.character)
Inputdf[] = lapply(Inputdf, function(col) sapply(col, function(x) unlist(strsplit(x,','))))

not.empty = function(x) length(x) > 0
out = data.frame()

for (r in 1:nrow(Inputdf)) {
  df2.intersect = lapply(Inputdf$df2, intersect, Inputdf$df1[[r]])
  df3.intersect = lapply(Inputdf$df3, intersect, Inputdf$df1[[r]])

  out[r, 'df1'] = r
  out[r, 'df2'] = Position(not.empty, df2.intersect, nomatch=0)
  out[r, 'df3'] = Position(not.empty, df3.intersect, nomatch=0)
  out[r, 'Numberdf1'] = length(Inputdf$df1[[r]])
  out[r, 'df2.1'] = paste(Find(not.empty, df2.intersect, nomatch=0), collapse=',')
  out[r, 'df3.1'] = paste(Find(not.empty, df3.intersect, nomatch=0), collapse=',')
}

out
#   df1 df2 df3 Numberdf1                df2.1         df3.1
# 1   1   0   1         4                    0 Q92793,Q09472
# 2   2   3   0         6               Q92828             0
# 3   3   4   2         3               Q6QNY0        Q6QNY0
# 4   4   2   4         7 P61158,O15143,O15144        O15511
# 5   5   1   3         2        Q06323,Q9UL46 Q06323,Q9UL46

注意:FindPosition 仅识别 first 匹配项。如果可能有多个匹配项,请使用which

编辑

多个匹配的版本说明

Inputdf[] = lapply(Inputdf, as.character)
Inputdf[] = lapply(Inputdf, function(col) sapply(col, function(x) unlist(strsplit(x,',\\s*'))))

not.empty = function(x) length(x) > 0
out = data.frame()

for (r in 1:nrow(Inputdf)) {
  df2.intersect = lapply(Inputdf$df2, intersect, Inputdf$df1[[r]])
  df3.intersect = lapply(Inputdf$df3, intersect, Inputdf$df1[[r]])

  out[r, 'df1'] = r
  out[r, 'df2'] = paste(which(sapply(df2.intersect, not.empty)), collapse=',')
  out[r, 'df3'] = paste(which(sapply(df3.intersect, not.empty)), collapse=',')
  out[r, 'Numberdf1'] = length(Inputdf$df1[[r]])
  out[r, 'df2.1'] = paste(unique(unlist(df2.intersect)), collapse=',')
  out[r, 'df3.1'] = paste(unique(unlist(df3.intersect)), collapse=',')
}

out[out==""] = "0"

【讨论】:

  • 有多个相似之处,是否可以改为这种方式,因为在真实数据上,它没有给出正确的答案
  • 我在上面发布了另一个示例,向您展示它不起作用!不知道问题出在哪里
  • @nik 在新示例中,有额外的空格分隔项目(“A,B”与“A,B”)
  • strsplit 参数更改为 ',\\s*'
  • 你能帮我做哪个吗?
猜你喜欢
  • 2019-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
  • 2016-11-22
  • 2017-02-28
  • 1970-01-01
相关资源
最近更新 更多