繁体   English   中英

在每行数据框上应用两列函数

[英]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 ,从我的其他尝试中,每次只有一个由单个字符组成的匹配子字符串时都会发生这种情况。

几点:

  1. 问题代码中的这一行:

     ones <- ones[order(ones[, 1]), ]

    应该是:

     ones <- ones[order(ones[, 1]), , drop = FALSE ]
  2. 定义longest.substring.vec ,它类似于longest.substring除了它接受向量ab而不仅仅是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.

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