我的一个数据输入如下所示:
O75663 O95456 O75663 O95456
O95400 O95670 O95400 O95670
O95433 O95433 O95801
O95456 P00352
O95670
df<- structure(
list(
V1 = structure(c(2L, 3L, 4L, 1L, 1L),
.Label = c("", "O75663", "O95400", "O95433"),
class = "factor"),
V2 = structure(c(2L, 3L, 1L, 1L, 1L),
.Label = c("", "O95456", "O95670"),
class = "factor"),
V3 = structure(1:5,
.Label = c("O75663", "O95400", "O95433", "O95456", "O95670"),
class = "factor"),
V4 = structure(c(2L, 3L, 4L, 5L, 1L),
.Label = c("", "O95456", "O95670", "O95801", "P00352"),
class = "factor")),
.Names = c("V1", "V2", "V3", "V4"),
class = "data.frame",
row.names = c(NA, -5L))
我的第二个数据输入如下:
O75663
O95400
O95433
O95456
O95670
O95801
P00352
P00492
我想知道第二个数据集中的每个字符串,其中可以找到第一个数据的列。它可能不属于任何一个,也可能是几个。我希望输出看起来如下:
strings column ids
O75663 1, 3
O95400 1, 3
O95433 1, 3
O95456 2, 3, 4
O95670 2, 3, 4
O95801 4
P00352 4
P00492 NA
新的strs
:
strs <- structure(
list(
strings = structure(c(2L, 3L, 4L, 5L, 6L, 7L, 1L, 1L),
.Label = c("", "O75663", "O95400", "O95433", "O95456", "O95670", "O95801"),
class = "factor"),
strings2 = structure(c(4L, 2L, 6L, 5L, 3L, 1L, 1L, 1L),
.Label = c("", "O75663", "O95433", "O95456", "P00352", "P00492"),
class = "factor"),
strings3 = structure(c(4L, 6L, 7L, 8L, 2L, 3L, 5L, 1L),
.Label = c("", "O75663", "O95400", "O95456", "O95670", "O95801", "P00352", "P00492"),
class = "factor"),
strings4 = structure(c(2L, 5L, 3L, 4L, 1L, 1L, 1L, 1L),
.Label = c("", "O95400", "O95456", "O95801", "P00492"),
class = "factor"),
strings5 = structure(c(8L, 2L, 7L, 1L, 3L, 6L, 5L, 4L),
.Label = c("O75663", "O95400", "O95433", "O95456", "O95670", "O95801", "P00352", "P00492"),
class = "factor")),
.Names = c("strings", "strings2", "strings3", "strings4", "strings5"),
class = "data.frame",
row.names = c(NA, -8L))
lut <- structure(
list(
V1 = c("O75663", "O95400", "O95433", NA, NA),
V2 = c("O95456", "O95670", NA, NA, NA),
V3 = c("O75663", "O95400", "O95433", "O95456", "O95670"),
V4 = c("O95456", "O95670", "O95801", "P00352", NA),
V1 = c("O75663", "O95400", "O95433", NA, NA),
V2 = c("O95456", "O95670", NA, NA, NA),
V3 = c("O75663", "O95400", "O95433", "O95456", "O95670"),
V4 = c("O95456", "O95670", "O95801", "P00352", NA)),
.Names = c("V1", "V2", "V3", "V4", "V1", "V2", "V3", "V4"),
row.names = c(NA, -5L), class = "data.frame")
df<- setDT(strs)[, paste0('colids_',seq_along(strs)) :=
lapply(.SD, function(x) toString(which(colSums(lut == x, na.rm=TRUE) > 0))),
by = 1:nrow(strs)][]
然后我收到此错误:
df1 == x
中的错误:未实施这些类型的比较 另外:警告信息:is.data.frame(x)
:
“Ops.data.frame
”的不兼容方法(“Ops.factor
”,“==
”)
答案 0 :(得分:4)
使用colSums
,which
,toString
和apply
组合的基础R的可能解决方案:
strs$colids <- apply(strs, 1, function(x) toString(which(colSums(lut == x, na.rm=TRUE) > 0)))
给出:
> strs
strings colids
1 O75663 1, 3
2 O95400 1, 3
3 O95433 1, 3
4 O95456 2, 3, 4
5 O95670 2, 3, 4
6 O95801 4
7 P00352 4
8 P00492
要查看每个部分的作用,首先查看lut == 'O75663'
的输出,它将为您提供TRUE/FALSE
表。通过将其包裹在colSums
中,您可以将TRUE/FALSE
加起来。 0
表示该列中该字符串不匹配,大于零的数字表示存在一个或多个匹配项。使用which
,您可以获得列索引,并将其包装在toString
中,您将获得具有匹配列索引的字符值。
此方法也可以使用data.table
或dplyr
:
library(data.table)
setDT(strs)[, colids := toString(which(colSums(lut == strings, na.rm=TRUE) > 0)), by = 1:nrow(strs)][]
library(dplyr)
strs %>% rowwise() %>% mutate(colids = toString(which(colSums(lut == strings, na.rm=TRUE) > 0)))
回复您的评论:strs
data.table
中多列的示例:
# create an extra strings column
set.seed(1)
strs$strings2 <- sample(strs$strings)
# create two 'colids' columns
library(data.table)
setDT(strs)[, c('colids1','colids2') := lapply(.SD, function(x) toString(which(colSums(lut == x, na.rm=TRUE) > 0))), by = 1:nrow(strs)][]
给出:
strings strings2 colids1 colids2
1: O75663 O95433 1, 3 1, 3
2: O95400 P00492 1, 3
3: O95433 O95456 1, 3 2, 3, 4
4: O95456 O95670 2, 3, 4 2, 3, 4
5: O95670 O75663 2, 3, 4 1, 3
6: O95801 P00352 4 4
7: P00352 O95400 4 1, 3
8: P00492 O95801 4
使用过的数据:
lut <- structure(list(V1 = c("O75663", "O95400", "O95433", NA, NA),
V2 = c("O95456", "O95670", NA, NA, NA),
V3 = c("O75663", "O95400", "O95433", "O95456", "O95670"),
V4 = c("O95456", "O95670", "O95801", "P00352", NA)),
.Names = c("V1", "V2", "V3", "V4"), class = "data.frame", row.names = c(NA, -5L))
strs <- structure(list(strings = c("O75663", "O95400", "O95433", "O95456", "O95670", "O95801", "P00352", "P00492")),
.Names = "strings", class = "data.frame", row.names = c(NA, -8L))
关于您添加到问题中的扩展示例:您获得该错误的原因是您尝试将因子变量与字符变量进行比较。查看sapply(strs,class)
和sapply(lut,class)
之间的输出差异:
> sapply(strs,class)
strings1 strings2 strings3 strings4 strings5
"factor" "factor" "factor" "factor" "factor"
> sapply(lut,class)
V1 V2 V3 V4 V5 V6 V7 V8
"character" "character" "character" "character" "character" "character" "character" "character"
因此,有必要先将factor
转换为character
,然后再进行比较。以下代码:
library(data.table)
setDT(strs)[, lapply(.SD, as.character)
][, paste0('colids.',seq_along(strs)) := lapply(.SD, function(x) toString(which(colSums(lut == x, na.rm=TRUE) > 0))),
by = 1:nrow(strs)][]
现在提供正确的输出:
strings1 strings2 strings3 strings4 strings5 colids.1 colids.2 colids.3 colids.4 colids.5
1: O75663 O95456 O95456 O95400 P00492 1, 3, 5, 7 2, 3, 4, 6, 7, 8 2, 3, 4, 6, 7, 8 1, 3, 5, 7
2: O95400 O75663 O95801 P00492 O95400 1, 3, 5, 7 1, 3, 5, 7 4, 8 1, 3, 5, 7
3: O95433 P00492 P00352 O95456 P00352 1, 3, 5, 7 4, 8 2, 3, 4, 6, 7, 8 4, 8
4: O95456 P00352 P00492 O95801 O75663 2, 3, 4, 6, 7, 8 4, 8 4, 8 1, 3, 5, 7
5: O95670 O95433 O75663 O95433 2, 3, 4, 6, 7, 8 1, 3, 5, 7 1, 3, 5, 7 1, 3, 5, 7
6: O95801 O95400 O95801 4, 8 1, 3, 5, 7 4, 8
7: O95670 O95670 2, 3, 4, 6, 7, 8 2, 3, 4, 6, 7, 8
8: O95456 2, 3, 4, 6, 7, 8
使用过的数据扩展示例:
strs <- structure(list(strings1 = structure(c(2L, 3L, 4L, 5L, 6L, 7L, 1L, 1L), .Label = c("", "O75663", "O95400", "O95433", "O95456", "O95670", "O95801"), class = "factor"),
strings2 = structure(c(4L, 2L, 6L, 5L, 3L, 1L, 1L, 1L), .Label = c("", "O75663", "O95433", "O95456", "P00352", "P00492"), class = "factor"),
strings3 = structure(c(4L, 6L, 7L, 8L, 2L, 3L, 5L, 1L), .Label = c("", "O75663", "O95400", "O95456", "O95670", "O95801", "P00352", "P00492"), class = "factor"),
strings4 = structure(c(2L, 5L, 3L, 4L, 1L, 1L, 1L, 1L), .Label = c("", "O95400", "O95456", "O95801", "P00492"), class = "factor"),
strings5 = structure(c(8L, 2L, 7L, 1L, 3L, 6L, 5L, 4L), .Label = c("O75663", "O95400", "O95433", "O95456", "O95670", "O95801", "P00352", "P00492"), class = "factor")),
.Names = c("strings1", "strings2", "strings3", "strings4", "strings5"), class = "data.frame", row.names = c(NA, -8L))
lut <- structure(list(V1 = c("O75663", "O95400", "O95433", NA, NA),
V2 = c("O95456", "O95670", NA, NA, NA),
V3 = c("O75663", "O95400", "O95433", "O95456", "O95670"),
V4 = c("O95456", "O95670", "O95801", "P00352", NA),
V5 = c("O75663", "O95400", "O95433", NA, NA),
V6 = c("O95456", "O95670", NA, NA, NA),
V7 = c("O75663", "O95400", "O95433", "O95456", "O95670"),
V8 = c("O95456", "O95670", "O95801", "P00352", NA)),
.Names = c("V1", "V2", "V3", "V4", "V5", "V6", "V7", "V8"), row.names = c(NA, -5L), class = "data.frame")