【问题标题】:Using mapply() For Column Row Comparison使用 mapply() 进行列行比较
【发布时间】:2017-12-09 16:24:21
【问题描述】:

我正在处理两个不同的大型数据集并尝试利用mapply() 来使迭代函数正常工作。

目标是从 Data_1 中逐列获取每个数据点,并将其与 Data_2 列中的两个数据点进行比较。因此,Data_1[1,1] 将仅与 Data_2[1,1]Data_2[2,1] 进行比较。更清楚地说,Data_1 中的 data1 列只会与 Data_2 中的 dataA 元素进行比较,因此没有交叉列比较。

数据_1:NxM

  data1       data2       data3      data4
-0.710003   -0.714271   -0.709946   -0.713645
-0.710458   -0.715011   -0.710117   -0.714157
-0.71071    -0.714048   -0.710235   -0.713515
-0.710255   -0.713991   -0.709722   -0.713972

Data_2:PxQ

  dataA       dataB       dataC      dataD
-0.71097    -0.714059   -0.70928    -0.714059
-0.710343   -0.714576   -0.709338   -0.713644

我之前写了一个for()while()基于循环的算法,但是运行时间与原始数据一样多。然后,我转向基于apply() 的逻辑,但在我调用的函数中仍然有循环,所以这并没有加快代码速度。基于my earlier question,我正在寻找更好的方法来使用mapply()

我无法想象的部分是列到行的比较以及mapply() 将如何递归地浏览它。如何使用mapply()lapply() 有效地完成这项工作?

任何建议都会有所帮助,谢谢。

【问题讨论】:

    标签: r performance optimization packages


    【解决方案1】:

    考虑一个嵌套的 apply 家庭调用:

    • mapply() - 外部:Data_1Data_2 的对应列之间的成对迭代
    • sapply - 内部:Data_1列中每个值的向量迭代,用于元素比较

    下面检查每个 Data_1 值是否介于 Data_2 的每一列的两个值之间:

    数据

    txt = '  data1       data2       data3      data4
    -0.710003   -0.714271   -0.709946   -0.713645
    -0.710458   -0.715011   -0.710117   -0.714157
    -0.71071    -0.714048   -0.710235   -0.713515
    -0.710255   -0.713991   -0.709722   -0.713972'
    
    Data_1 <- read.table(text=txt, header=TRUE)
    
    txt = ' dataA       dataB       dataC      dataD
    -0.71097    -0.714059   -0.70928    -0.714059
    -0.710343   -0.714576   -0.709338   -0.713644'
    
    Data_2 <- read.table(text=txt, header=TRUE)
    

    代码

    check_inbetween <- function(x,y){
      sapply(x, function(i) (i > y[1] & i < y[2]))
    }
    
    inbetween_matrix <- mapply(check_inbetween, Data_1, Data_2)
    
    inbetween_matrix
    #      data1 data2 data3 data4
    # [1,] FALSE FALSE FALSE  TRUE
    # [2,]  TRUE FALSE FALSE FALSE
    # [3,]  TRUE FALSE FALSE FALSE
    # [4,] FALSE FALSE FALSE  TRUE
    

    【讨论】:

    • 谢谢@Parfait,我猜sweep() 也可以是used
    • 可能。我从未使用过sweep()。这个实现有一个有趣的嵌套扫描。我的尝试似乎没有回收该函数,而仅在数据集的第一列上运行:sweep(as.matrix(Data_1), 1, as.matrix(Data_2), FUN = function(x,y) (x &gt; y[1] &amp; x &lt; y[2]), check.margin = FALSE)
    【解决方案2】:

    这是基于data.table 的一种解决方案,但如果您使用的是data.frame 或matrix,它应该很容易适应。要达到您想要的效果,您必须使用一个lapply 而不是另一个lapply。较高的一个迭代列,它调用另一个迭代行。

    library(data.table)
    
    # it gets all elements of column 'j' to do diff computation
    get_column_diff <- function(dt_1, dt_2, j){
    
            get_point_diff <- function(i){
                    # it should return a vector with all differences 
                    # in comparison of the point (i,j)
                    unlist(dt_1[i, ..j]) - unlist(dt_2[, ..j])
            }
    
    
            i_rows <- 1:nrow(dt_1)
            lapply(X=i_rows, FUN=get_point_diff)
    
    }
    
    j_cols <- 1:ncol(Data_1)
    lapply(FUN=get_column_diff, dt_1=Data_1, dt_2=Data_2, X=j_cols)
    

    函数返回一个列表列表,列表中的每个元素都是列结果,其元素是带有行结果的列表。

    关于速度增益,如果没有基准比较,我不能说它会有多快,但可能它会更快任何循环。

    【讨论】:

    • 谢谢@RafaelToledo。您的回答会有所帮助,但我需要深入了解 unlist()list() 的工作原理。另外,j_cols &lt;- 1:ncol(dt_1) 行会导致错误,对吧?因为dt_1 在那之后被分配了Data_1
    • 我的错,我会更新它,里面的ncol 必须是Data_1。要组织您的输出,您必须首先考虑您想要的方式,因为您的输出将类似于(n x n) x n
    猜你喜欢
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    • 2013-02-13
    • 2012-01-14
    • 2014-11-29
    相关资源
    最近更新 更多