【问题标题】:R: enumerate column combinations of a matrixR:枚举矩阵的列组合
【发布时间】:2020-08-14 18:30:42
【问题描述】:

(编辑说明:我将标题更改为“R:枚举矩阵的列组合”,从“R grep:将字符串矩阵匹配到列表”以更好地反映解决方案)

我正在尝试将字符串矩阵与列表匹配:以便我最终可以在data.frame 的后续操作中将该矩阵用作映射。

这第一部分按预期工作,返回所有可能的对、三元组和四元组组合的列表(尽管也许这种方法已经创建了我的绑定?):

priceList <- data.frame(aaa = rnorm(100, 100, 10), bbb = rnorm(100, 100, 10), 
            ccc = rnorm(100, 100, 10), ddd = rnorm(100, 100, 10), 
            eee = rnorm(100, 100, 10), fff = rnorm(100, 100, 10), 
            ggg = rnorm(100, 100, 10))

getTrades <- function(dd, Maxleg=3)
{
    nodes <- colnames(dd)
    tradeList <- list()
    for (i in 2:Maxleg){
        tradeLeg <- paste0('legs',i)
        tradeList[[tradeLeg]] <- combn(nodes, i)
    }
    return(tradeList)
}

tradeCombos <- getTrades(priceList, 4)

我现在想把这个可能的组合列表变成交易。例如:

> tradeCombos[[1]][,1]
[1] "aaa" "bbb"

需要最终变成priceList[,2] - priceList[,1],以此类推。

我用grep 和类似的命令尝试了一些方法,感觉我已经接近了以下:

LocList <- sapply(tradeCombos[[1]], regexpr, colnames(priceList))

但是该格式不太适合下一步。

理想情况下,LocList[1] 会返回类似:1 2

假设tradeCombos[[1]][,1] == "aaa" "bbb".

有人可以帮忙吗?

__

在以下所有答案的帮助下,我现在得到了:

colDiff <- function(x) 
{
    Reduce('-', rev(x))
}

getTrades <- function(dd, Maxleg=3)
{
    tradeList <- list()
    for (i in 2:Maxleg){
        tradeLeg <- paste0('legs',i)
        tradeLegsList <- combn(names(dd), i, 
            function(x) dd[x], simplify = FALSE)
        nameMtx <- combn(names(dd), i)
        names(tradeLegsList) <- apply(nameMtx, MARGIN=2, 
            FUN=function(x) paste(rev(x), collapse='*'))
        tradeList[[tradeLeg]] <- lapply(tradeLegsList, colDiff) 
    }
    return(tradeList)
}

tradeCombos <- getTrades(priceList, 4)

这保留了组成部分的名称,这是我试图实现的一切。

非常感谢大家的帮助。

【问题讨论】:

  • 顺便熟悉一下combn!试试combn(names(priceList, 2))combn(names(priceList, 3)),看看你想出了什么。
  • @mrdwab,我基本上在getTrades 函数中使用combn(names(priceList), 3)tradeList[[tradeLeg]] &lt;- combn(nodes, i)。然而,往下看,很明显我有很多东西要了解combn。非常感谢所有的帮助。

标签: r


【解决方案1】:

哇...忽略下面的所有内容并跳转到更新

正如我在评论中提到的,您可以使用combn。此解决方案不会将您带到最后一步,而是创建一个data.frames 列表。从那里,很容易使用lapply 来完成您的最后一步。

这是简化的函数:

TradeCombos <- function(dd, MaxLeg) {
  combos = combn(names(dd), MaxLeg)
  apply(combos, 2, function(x) dd[x])
}

要使用它,只需指定您的数据集和您要查找的组合数量。

TradeCombos(priceList, 3)
TradeCombos(priceList, 4)

继续:@mplourde 向您展示了如何使用Reduce 进行连续减法。这里将采用类似的方法:

cumDiff <- function(x) Reduce("-", rev(x))
lapply(TradeCombos(priceList, 3), cumDiff)

通过将TradeCombos 函数的输出保持为listdata.frames,您将留出更多的灵活性空间。例如,如果你想要行总和,你可以简单地使用lapply(TradeCombos(priceList, 3), rowSums);对于您想要应用的任何功能,都可以采用类似的方法。

更新

我不确定为什么@GSee 没有添加这个作为答案,但我认为它非常棒:

获取您的listdata.frames,如下所示:

combn(names(priceList), 3, function(x) priceList[x], simplify = FALSE)

根据需要提前。 (例如,使用我们创建的cumDiff 函数:combn(names(priceList), 2, function(x) cumDiff(priceList[x]), simplify = FALSE)。)

【讨论】:

  • 您知道combn 接受FUN 参数吗?即你真的不需要apply
  • @GSee,我没有,但那是 真棒。感谢您指出!
  • @GSee,我可以把它转给你吗:-)
  • 不要卖空自己。 combn 正在做这项工作,无论你是否喂它FUN
  • +1 并被接受。谢谢,我从这个答案中学到了很多东西。非常感激。丢失的位 - 但我正在处理它 - 它保留了 colnames - 所以我可以看到输出中的每个向量是如何构成的。
【解决方案2】:

这将使用lapplyapplyReduce 实现您的最终目标。

lapply(tradeCombos, 
 function(combos) 
 apply(combos, MARGIN=2, FUN=function(combo) Reduce('-', priceList[rev(combo)])))

combo 是来自tradeCombos 中的组合矩阵之一的列。 rev(combo) 反转列,因此最后一个值是第一个。从data.frame 中选择列子集的R 语法是DF[col.names],因此priceList[rev(combo)]priceList 的子集,只有combo 中的列,以相反的顺序排列。 data.frames 实际上只是 lists 的列,因此任何旨在迭代 lists 的函数都可以用于迭代 data.frame 中的列。 Reduce 就是这样一种功能。 Reduce 接受一个函数(在本例中为减法函数 -)和一个 list 参数,然后在 list 中的参数上连续调用该函数,并使用上一次调用的结果,例如 (( (arg1 - arg2) - arg3) - arg4)。

您重命名tradeCombos 中的列,以便最终的列名反映它们的来源:

tradeCombos <- lapply(tradeCombos, 
    function(combos) {
        dimnames(combos)[[2]] <- apply(combos, 
            MARGIN=2, 
            FUN=function(combo) paste(rev(combo), collapse='-')
        )
        return(combos)
    }
)

【讨论】:

  • +1,谢谢 - 非常有用。我不知道其中的许多可能性。是否可以使附加到每个列表位置的矩阵的列名反映其构造中使用的列名?
  • apply 继承其参数的列名。查看我的编辑以重命名tradeCombos中的列
  • 不,你明白了,伙计。你解决了我所有的问题。不能要求更多 - 所以我切换了接受。回答的每个人都很棒。
【解决方案3】:

tradeCombos 是带有 matrix 元素的 list。因此,tradeCombos[[1]]matrixapply 更适合。

apply(tradeCombos[[1]],1,function(x) match(x,names(priceList)))
      [,1] [,2]
 [1,]    1    2
 [2,]    1    3
 [3,]    1    4
 [4,]    1    5
 [5,]    1    6
 [6,]    1    7
 [7,]    2    3
 [8,]    2    4
 [9,]    2    5
[10,]    2    6
[11,]    2    7
[12,]    3    4
[13,]    3    5
[14,]    3    6
[15,]    3    7
[16,]    4    5
[17,]    4    6
[18,]    4    7
[19,]    5    6
[20,]    5    7
[21,]    6    7

顺便说一句,无论如何,您都可以使用字符串形式进行子集化,例如priceList[,"aaa"]

【讨论】:

  • +1,谢谢。这正是我最初提出的问题的答案(并认为我需要解决)。将您的答案与您的偶然见解相结合产生了apply(tradeCombos[[1]], 2, function(x) priceList[x]),这非常有用。
  • 终于,玩了一会儿,我把getTrades函数的一行改成了:tradeList[[tradeLeg]] &lt;- apply(combn(colnames(dd), i), 2, function(x) dd[x])
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 1970-01-01
  • 2017-05-03
相关资源
最近更新 更多