我有三个或更多的自变量表示为R向量,如下所示:
A <- c(1,2,3)
B <- factor(c('x','y'))
C <- c(0.1,0.5)
Run Code Online (Sandbox Code Playgroud)
我想采用所有这些产品的笛卡尔积,并将结果放入数据框中,如下所示:
A B C
1 x 0.1
1 x 0.5
1 y 0.1
1 y 0.5
2 x 0.1
2 x 0.5
2 y 0.1
2 y 0.5
3 x 0.1
3 x 0.5
3 y 0.1
3 y 0.5
Run Code Online (Sandbox Code Playgroud)
我可以通过手动写出调用来执行此操作rep:
d <- data.frame(A = rep(A, times=length(B)*length(C)),
B = rep(B, times=length(A), each=length(C)),
C = rep(C, each=length(A)*length(B))
Run Code Online (Sandbox Code Playgroud)
但是必须有更优雅的方式去做,是吗? product在itertools部分工作中,但我找不到任何方法来吸收迭代器的输出并将其放入数据框中.有什么建议?
ps此计算的下一步看起来像
d$D <- f(d$A, d$B, d$C)
Run Code Online (Sandbox Code Playgroud)
所以如果你知道一次做两个步骤的方法,这也会有所帮助.
Ram*_*ath 67
您可以使用 expand.grid(A, B, C)
编辑:使用do.call实现第二部分的替代方法,是函数mdply.这是代码
d = expand.grid(x = A, y = B, z = C)
d = mdply(d, f)
Run Code Online (Sandbox Code Playgroud)
使用一个简单的函数'paste'来说明它的用法,你可以试试
d = mdply(d, 'paste', sep = '+');
Run Code Online (Sandbox Code Playgroud)
mis*_*ite 17
有一个操作数据帧的函数,在这种情况下很有用.
它可以产生各种连接(在SQL术语中),而笛卡尔积则是一种特殊情况.
您必须首先将varible转换为数据帧,因为它将数据帧作为参数.
所以这样的事情会做:
A.B=merge(data.frame(A=A), data.frame(B=B),by=NULL);
A.B.C=merge(A.B, data.frame(C=C),by=NULL);
Run Code Online (Sandbox Code Playgroud)
唯一需要关心的是行没有按照您的描述进行排序.您可以根据需要手动对它们进行排序.
__CODE__
"如果by和.x和by.y的长度为0(长度为零的向量或NULL),则结果r为x和y的笛卡尔乘积"
请参阅此网址以获取详细信息:http://stat.ethz.ch/R-manual/R-patched/library/base/html/merge.html
这是两种方法,使用Ramnath的建议expand.grid:
f <- function(x,y,z) paste(x,y,z,sep="+")
d <- expand.grid(x=A, y=B, z=C)
d$D <- do.call(f, d)
Run Code Online (Sandbox Code Playgroud)
需要注意的是do.call在作品d"原样"因为data.frame是一个list.但是do.call希望列名d匹配参数名f.
考虑使用出色的data.table库来提高表达力和速度。它使用相当简单的统一语法处理许多plyr用例(关系分组依据)以及转换,子集和关系联接。
library(data.table)
d <- CJ(x=A, y=B, z=C) # Cross join
d[, w:=f(x,y,z)] # Mutates the data.table
Run Code Online (Sandbox Code Playgroud)
或一行
d <- CJ(x=A, y=B, z=C)[, w:=f(x,y,z)]
Run Code Online (Sandbox Code Playgroud)
tidyr可以使用一个库tidyr::crossing(顺序将与OP中相同):
library(tidyr)
crossing(A,B,C)
# A tibble: 12 x 3
# A B C
# <dbl> <fct> <dbl>
# 1 1 x 0.1
# 2 1 x 0.5
# 3 1 y 0.1
# 4 1 y 0.5
# 5 2 x 0.1
# 6 2 x 0.5
# 7 2 y 0.1
# 8 2 y 0.5
# 9 3 x 0.1
# 10 3 x 0.5
# 11 3 y 0.1
# 12 3 y 0.5
Run Code Online (Sandbox Code Playgroud)
下一步将是使用tidyverse,尤其是purrr::pmap*家庭:
library(tidyverse)
crossing(A,B,C) %>% mutate(D = pmap_chr(.,paste,sep="_"))
# A tibble: 12 x 4
# A B C D
# <dbl> <fct> <dbl> <chr>
# 1 1 x 0.1 1_1_0.1
# 2 1 x 0.5 1_1_0.5
# 3 1 y 0.1 1_2_0.1
# 4 1 y 0.5 1_2_0.5
# 5 2 x 0.1 2_1_0.1
# 6 2 x 0.5 2_1_0.5
# 7 2 y 0.1 2_2_0.1
# 8 2 y 0.5 2_2_0.5
# 9 3 x 0.1 3_1_0.1
# 10 3 x 0.5 3_1_0.5
# 11 3 y 0.1 3_2_0.1
# 12 3 y 0.5 3_2_0.5
Run Code Online (Sandbox Code Playgroud)