데카르트 곱 데이터 프레임
다음과 같이 R 벡터로 표현되는 세 개 이상의 독립 변수가 있습니다.
A <- c(1,2,3)
B <- factor(c('x','y'))
C <- c(0.1,0.5)
그리고 나는 그들 모두의 데카르트 곱을 취하고 결과를 다음과 같이 데이터 프레임에 넣고 싶습니다.
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
수동으로 다음과 같은 호출을 작성하여이를 수행 할 수 있습니다 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))
하지만 더 우아한 방법이 있어야합니다. product
in itertools
은 작업의 일부를 수행하지만 반복기의 출력을 흡수하여 데이터 프레임에 넣는 방법을 찾을 수 없습니다. 어떤 제안?
ps이 계산의 다음 단계는 다음과 같습니다.
d$D <- f(d$A, d$B, d$C)
두 단계를 동시에 수행하는 방법을 알고 있다면 도움이 될 것입니다.
당신이 사용할 수있는 expand.grid(A, B, C)
편집 : 두 번째 부분을 달성하기 위해 do.call을 사용하는 대안은 mdply 함수입니다. 여기에 코드가 있습니다
d = expand.grid(x = A, y = B, z = C)
d = mdply(d, f)
사소한 기능 '붙여 넣기'를 사용하여 사용법을 설명하기 위해 시도해 볼 수 있습니다.
d = mdply(d, 'paste', sep = '+');
이 경우에 도움이되는 데이터 프레임을 조작하는 함수가 있습니다.
다양한 조인 (SQL 용어로)을 생성 할 수 있지만 Cartesian 곱은 특별한 경우입니다.
데이터 프레임을 매개 변수로 사용하기 때문에 먼저 변수를 데이터 프레임으로 변환해야합니다.
그래서 다음과 같이 할 것입니다.
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);
주의해야 할 것은 행이 묘사 한대로 정렬되지 않는다는 것입니다. 원하는대로 수동으로 정렬 할 수 있습니다.
merge(x, y, by = intersect(names(x), names(y)),
by.x = by, by.y = by, all = FALSE, all.x = all, all.y = all,
sort = TRUE, suffixes = c(".x",".y"),
incomparables = NULL, ...)
"by.x 및 by.y의 길이가 0 (길이 0 벡터 또는 NULL) 인 경우 결과 r은 x와 y의 데카르트 곱입니다."
자세한 내용은 다음 URL을 참조하십시오. 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)
참고 do.call
작동 d
a가 있기 때문 "으로는-는" data.frame
A는 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
또는 한 줄로
d <- CJ(x=A, y=B, z=C)[, w:=f(x,y,z)]
라이브러리 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
다음 단계는 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
교차 조인 사용 sqldf
:
library(sqldf)
A <- data.frame(c1 = c(1,2,3))
B <- data.frame(c2 = factor(c('x','y')))
C <- data.frame(c3 = c(0.1,0.5))
result <- sqldf('SELECT * FROM (A CROSS JOIN B) CROSS JOIN C')
나는 그 표준 기능을 결코 기억할 수 없다 expand.grid
. 여기에 또 다른 버전이 있습니다.
crossproduct <- function(...,FUN='data.frame') {
args <- list(...)
n1 <- names(args)
n2 <- sapply(match.call()[1+1:length(args)], as.character)
nn <- if (is.null(n1)) n2 else ifelse(n1!='',n1,n2)
dims <- sapply(args,length)
dimtot <- prod(dims)
reps <- rev(cumprod(c(1,rev(dims))))[-1]
cols <- lapply(1:length(dims), function(j)
args[[j]][1+((1:dimtot-1) %/% reps[j]) %% dims[j]])
names(cols) <- nn
do.call(match.fun(FUN),cols)
}
A <- c(1,2,3)
B <- factor(c('x','y'))
C <- c(.1,.5)
crossproduct(A,B,C)
crossproduct(A,B,C, FUN=function(...) paste(...,sep='_'))
ReferenceURL : https://stackoverflow.com/questions/4309217/cartesian-product-data-frame
'program story' 카테고리의 다른 글
별도의 하위 폴더에 이미지 / 글꼴을 출력하도록 웹팩 구성 (0) | 2020.12.25 |
---|---|
컨트롤러에서 ModelState.isValid 수동 설정 (0) | 2020.12.24 |
객체 목록에 특정 값이있는 속성이 포함되어 있는지 확인 (0) | 2020.12.24 |
코드로 LINQPad 결과 창을 지울 수 있습니까? (0) | 2020.12.24 |
svn 오류 413 요청 엔터티가 너무 큼의 원인은 무엇입니까? (0) | 2020.12.24 |