【问题标题】:Mapply on a function with conditional expressions使用条件表达式映射函数
【发布时间】:2018-03-29 20:42:28
【问题描述】:

背景:PDF Parse 我的程序在扫描的 PDF 文档中查找数据。我创建了一个 CSV,其中的行表示要在 PDF 中搜索的各种参数,以及可能包含这些参数的不同文档风格的列。每个参数都有不同的标识符,具体取决于文档的类型。列标题使用点分隔来按类型、子类型...唯一标识文档,如下所示:type.subtype.s_subtype.s_s_subtype

    t.s.s2.s3 t.s.s2.s3 t.s.s2.s3 t.s.s2.s3 ...
p1    str1                 str2
p2               str3      str4
p3    str5                           str6
p4               str7
...

我正在阅读 PDF 文件,根据文件路径,它们可以被唯一地分类为其中一种类型。我可以将各种逻辑条件应用于给定文件路径的子字符串,并基于此输出NxM 布尔矩阵,其中N = NROW(filepath_vector)M = ncol(params_csv)。该矩阵将显示给定文件在类型中的成员资格,该类型为 TRUEFALSE 其他地方。

        t.s.s2.s3 t.s.s2.s3 t.s.s2.s3 t.s.s2.s3 ...
fpath1    FALSE     FALSE     TRUE      FALSE
fpath2    FALSE     TRUE      FALSE     FALSE
fpath3    FALSE     TRUE      FALSE     FALSE         
fpath4    FALSE     FALSE     FALSE     TRUE
...

我的解决方案:我正在尝试将函数应用于以向量作为参数的矩阵,并将向量的第一个元素应用于第一行,将第二个元素应用于第二行行等...但是,该函数具有条件行为,具体取决于所应用的向量的元素。

我知道这与下面的问题(我的参考点)非常相似,但我的函数中的条件让我感到困惑。我提供了以下问题的简化可重现示例。

R: Apply function to matrix with elements of vector as argument

set.seed(300)

x <- y <- 5
m <- matrix(rbinom(x*y,1,0.5),x,y)

v <- c("321", "", "A160470", "7IDJOPLI", "ACEGIKM")

f <- function(x) {
  sapply(v, g <- function(y) {
    if(nchar(y)==8) {x=x*2
    } else if (nchar(y)==7) {
      if(grepl("^[[:alpha:]]*$", substr(y, 1, 1))) {x=x*3}
      else {x}
    } else if (nchar(y)<3) {x=x*4
    } else {x=x-2}
  })
}

mapply(f, as.data.frame(t(m)))

期望的输出:

 #       [,1] [,2] [,3] [,4] [,5]
 # [1,]   -1    0   -1   -1   -1
 # [2,]    4    4    0    4    0
 # [3,]    3    0    3    3    0
 # [4,]    2    0    2    2    0
 # [5,]    1    1    1    1    0

但我收到此错误:

 Error in if (y == 8) { : missing value where TRUE/FALSE needed

似乎无法找出错误,或者如果我在整个方法的其他地方被误导,任何想法都值得赞赏。

更新(2018 年 4 月 3 日):

为了可重复性,我提供了这个作为玩具示例,但我认为使用与我的实际代码类似的东西和@grand_chat 的优秀解决方案会提供更多信息。希望这对遇到类似问题的人有所帮助。

chk <- c(NA, "abc.TRO", "def.TRO", "ghi.TRO", "kjl.TRO", "mno.TRO")
len <- c(8, NA, NA)
seed <- c(FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE)
A = matrix(seed, nrow=3, ncol=6, byrow=TRUE)

pairs <- mapply(list, as.data.frame(t(A)), len, SIMPLIFY=F)

f <- function(pair) {
  x = unlist(pair[[1]])
  y = pair[[2]]
  if(y==8 & !is.na(y)) {
    x[c(grep("TRO", chk))] <- (x[c(grep("TRO", chk))] & TRUE)
  } else {x <- (x & FALSE)}
  return(x)
}

t(mapply(f, pairs))

输出:

# $v1       
# [1,]    FALSE   TRUE    TRUE    FALSE   FALSE   FALSE
# $v2
# [2,]    FALSE   FALSE   FALSE   FALSE   FALSE   FALSE
# $v3
# [3,]    FALSE   FALSE   FALSE   FALSE   FALSE   FALSE

【问题讨论】:

  • 啊,对不起!刚刚编辑和更新它。

标签: r apply


【解决方案1】:

您正在并行处理向量v 的元素和矩阵m 的行(数据框t(m) 的列),因此您可以将相应的元素压缩到一个对列表中并处理对。试试这个:

x <- y <- 5
m <- matrix(rbinom(x*y,1,0.5),x,y)

v <- c("321", "", "A160470", "7IDJOPLI", "ACEGIKM")

# Zip into pairs:
pairs <- mapply(list, as.data.frame(t(m)), v, SIMPLIFY=F)

# Define a function that acts on pairs:
f <- function(pair) {
    x = pair[[1]]
    y = pair[[2]]
    if(nchar(y)==8) {x=x*2
    } else if (nchar(y)==7) {
      if(grepl("^[[:alpha:]]*$", substr(y, 1, 1))) {x=x*3}
      else {x}
    } else if (nchar(y)<3) {x=x*4
    } else {x=x-2}
  }

# Apply it:
mapply(f, pairs, SIMPLIFY=F)

结果:

$V1
[1] -2 -1 -2 -2 -1

$V2
[1] 4 4 0 0 4

$V3
[1] 3 3 3 3 0

$V4
[1] 2 0 2 2 0

$V5
[1] 0 0 3 0 3

(这与您想要的输出不符,因为您似乎没有正确应用您的函数f。)

【讨论】:

  • 感谢您的解决方案!我试图将它应用到我的实际代码中,但最终得到了无法解决的奇怪输出,因此我更新了我的问题 - 如果您有任何想法,将不胜感激。我不确定接受您的解决方案是否会关闭问题,因此人们将无法看到它,所以我会暂时搁置 - 但我认为这是最好的方法。
  • 没关系 - 想通了!出于说明目的,更新了我的问题,以使用我的实际代码应用您的解决方案。
猜你喜欢
  • 1970-01-01
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
  • 1970-01-01
  • 2020-07-24
  • 2021-03-16
  • 2019-09-14
相关资源
最近更新 更多