3

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

我正在尝试将字符串矩阵与列表匹配:以便我最终可以在稍后对 a 的操作中将该矩阵用作映射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)

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

非常感谢大家的帮助。

4

3 回答 3

3

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

正如我在评论中提到的,您可以使用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函数的输出保持为 a listof data.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)。)

于 2012-09-11T17:20:55.487 回答
2

lapply这可以使用、apply和来获得您的最终目标Reduce

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

combo是 中的组合矩阵之一的列tradeCombosrev(combo)反转列,因此最后一个值是第一个。从 a 中选择列子集的R语法data.frameDF[col.names],因此priceList[rev(combo)]是 的子集,priceList仅包含 中的列combo,以相反的顺序排列。data.frames 实际上只是lists 列,因此任何旨在迭代lists 的函数都可以用于迭代 a 中的列data.frameReduce就是这样一种功能。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)
    }
)
于 2012-09-11T11:47:04.810 回答
1

tradeCombos是一个listwithmatrix元素。因此,tradeCombos[[1]]是一个更适合matrix哪个。apply

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"]

于 2012-09-11T11:44:41.153 回答