(编辑注释:我将标题更改为“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)
这保留了构成部分的名称,是我试图实现的一切。
非常感谢大家的帮助。
答案 0 :(得分: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
函数的输出保持为list
的{{1}},您将为灵活性留出更多空间。例如,如果你想要行总和,你可以简单地使用data.frame
;对于您想要应用的任何功能,都可以采用类似的方法。
我不确定为什么@GSee没有将此作为答案添加,但我认为它非常棒:
按如下方式获取lapply(TradeCombos(priceList, 3), rowSums)
list
:
data.frame
根据需要前进。 (例如,使用我们创建的combn(names(priceList), 3, function(x) priceList[x], simplify = FALSE)
函数:cumDiff
。)
答案 1 :(得分:2)
这可以使用lapply
,apply
和Reduce
来实现最终目标。
lapply(tradeCombos,
function(combos)
apply(combos, MARGIN=2, FUN=function(combo) Reduce('-', priceList[rev(combo)])))
combo
是来自tradeCombos
中某个组合矩阵的列。 rev(combo)
会反转列,因此最后一个值是第一个。用于从R
选择列子集的data.frame
语法为DF[col.names]
,因此priceList[rev(combo)]
是priceList
的子集,仅包含{{1}中的列,以相反的顺序。 combo
实际上只是data.frame
列,因此任何旨在迭代list
的函数都可用于迭代list
中的列。 data.frame
就是这样一个功能。 Reduce
接受一个函数(在本例中为减法函数Reduce
)和-
个参数,然后在list
中的参数上连续调用函数,其结果为上一次调用,例如,(((arg1 - arg2) - arg3) - arg4)。
您重命名list
中的列,以便最终的列名称反映其来源:
tradeCombos
答案 2 :(得分:1)
tradeCombos
是具有list
元素的matrix
。因此,tradeCombos[[1]]
是matrix
,apply
更适合。{/ p>
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"]