[英]Applying a function of two columns over each row of data frame
我有一个从两个字符串返回最长公共子串的函数:
longest.substring <-function(a,b)
{
A <- strsplit(a, "")[[1]]
B <- strsplit(b, "")[[1]]
L <- matrix(0, length(A), length(B))
ones <- which(outer(A, B, "=="), arr.ind = TRUE)
ones <- ones[order(ones[, 1]), ]
if(length(ones)!=0){
for(i in 1:nrow(ones)) {
v <- ones[i, , drop = FALSE]
L[v] <- ifelse(any(v == 1), 1, L[v - 1] + 1)
}
paste0(A[(-max(L) + 1):0 + which(L == max(L), arr.ind = TRUE)[1]], collapse = "")
}
}
longest.substring("hello world","hella old") #returns "hell"
longest.substring("abc","def") #returns nothing
最初在确定一个常见模式中找到,我添加了 if 子句来处理根本没有子字符串匹配的字符串。 正如代码中的示例所示,它工作正常,但我在将其应用于我的数据集时遇到了问题。 对于它的每一行,我想对两列的值使用此函数并将结果放入第三列。 我试了几次,例如:
table1$LCS <- mapply(longest.substring, table1$col1, table1$col2)
table1$LCS <- apply(table1[,c("col1","col2")], 1, function(x)
longest.substring(x["col1"],x["col2"]))
两种方式(我使用mapply
在这些列之间运行adist
并且工作正常)都会返回错误:
Error in 1:nrow(ones) : argument of length 0
从我的运行它只是两个字符串的测试,这是之前我加入时发生的事情if
,那么函数“遗漏”这一条款,并尝试运行for
它导致错误。
另外我想指出我的数据集非常大(几千行),所以我认为for
循环需要很长时间才能完成。
编辑也进行了for
循环,但它返回与上述相同的错误。
for (i in 1:nrow(Adresy_baza_match)){
Adresy_baza_match[i,"LCS"] <- longest.substring(Adresy_baza_match[i,4], Adresy_baza_match[i,5])
}
编辑我设法隔离哪一行导致错误:
a b
921 BRUSKIEGO PLATYNOWA
922 BRUSKIEGO BPAHIERONIMAROZRAŻEWSKIEGO
923 BRUSKIEGO BPAKONSTANTYNADOMINIKA
第一行似乎导致它:
x <-longest.substring("BRUSKIEGO", "PLATYNOWA")
在这种情况下(逐行运行函数代码length(ones)
为 2,而nrow(ones)
返回NULL
,从我的其他尝试中,每次只有一个由单个字符组成的匹配子字符串时都会发生这种情况。
几点:
问题代码中的这一行:
ones <- ones[order(ones[, 1]), ]
应该是:
ones <- ones[order(ones[, 1]), , drop = FALSE ]
定义longest.substring.vec
,它类似于longest.substring
除了它接受向量a
和b
而不仅仅是scalars 。 它还将其参数强制转换为字符并将 NULL 替换为 NA 以确保结果是字符向量而不是列表。 现在试试这个:
longest.substring.vec <- function(a, b, default = NA_character_, USE.NAMES = FALSE) { a <- as.character(a) b <- as.character(b) m <- mapply(longest.substring, a, b, USE.NAMES = USE.NAMES) m[lengths(m) == 0] <- default unlist(m) }
要测试这两个更改:
tab <- data.frame(a = c("hello, world", "abc"), b = c("hella old", "def"))
transform(tab, c = longest.substring.vec(a, b))
## a b c
## 1 hello, world hella old hell
## 2 abc def <NA>
更新:
补充点 1. 重新排列演示。
GrpString
包提供了一个更简单、更强大的解决方案。
s <- c("hello world","hello old", "hello")
GrpString::CommonPatt(s) %>%
filter(Freq_str == length(s)) %>% filter(Length == max(Length)) %>%
select(Pattern) %>% unlist(use.names = F)
检查GrpString::CommonPatt(s)
的输出以获取有关常见模式的更多信息
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.