2011-04-26 2 views
10

그룹화 인수에 따라 행별로 data.frame을 분할하는 것이 매우 쉽습니다. 그러나 어떻게 컬럼별로 나누고 함수를 적용 할 수 있습니까?그룹화 변수를 사용하여 data.frame을 열별로 나누기

my.df <- data.frame(a = runif(10), 
     b = runif(10), 
     c = runif(10), 
     d = runif(10)) 
grp <- as.factor(c(1,1, 2,2)) 

나는 그룹별로 콜럼 (colum)을 의미합니다.

나는 지금까지 가난한 사람의 적용입니다.

lapply(as.list(as.numeric(levels(grp))), FUN = function(x, cn, data) { 
      rowMeans(data[grp %in% x]) 
     }, cn = grp, data = my.df) 

편집 참여에 대한 여러분 모두 감사합니다. 나는 10 복제 *를 달리고 나의 working data.frame에는 대략 22000의 줄이있다. 이것들은 초 단위의 결과입니다.

Roman: 2.19 
Joris: 4.60 
Joris #2: 3.79 #changed sapply to lapply as suggested by Joris in the [R chatroom][1]. 
Gavin: 4.70 
James & EDi: > 200 # * ran only one replicate due to the large order of magnitude difference 

당면한 작업에 대한 래퍼 기능이 없다는 것이 이상하게 들리 더라고요. 언젠가는 언젠가는 우리가 할 수있을 것입니다

apply(X = my.df, MARGIN = 3, INDEX = my.groups, FUN = mean) # :) 
+0

데이터 프레임은 10 개 행을 가지고 있으며, GRP는 4 개 값이 있습니다. 그들은 어떻게 일치시켜야합니까? – hadley

+0

@hadley : 데이터 프레임에는 4 개의 열이 있고 grp에는 4 개의 값이 있으므로 최대 일치 ... –

+0

@hadley, 행이 아닌 열로 분할하므로 length (my.df)와 일치해야합니다. == 길이 (grp). –

답변

6

당신은 더 편리한 형태로하지만, 같은 논리를 사용할 수 있습니다

sapply(levels(grp),function(x)rowMeans(my.df[which(grp==x)])) 
+0

그 버전은 내가 Joris에게 보여 줬던 것보다 ~ x2 빠릅니다. 일반적으로 색인 생성이 가능합니다.+1 –

0

이것은 작동합니까?

aggregate(t(my.df), list(grp), mean) 
+0

집계 +1을 사용해보세요. – Ramnath

+0

이 방법은 grp 벡터가 올바른 길이가 아니라는 사실을 자동으로 무시합니다. – hadley

0

방법에 대해 : 목록에

my.df2 <- data.frame(t(my.df),grp) 
aggregate(.~grp,my.df2,mean) 
+0

죄송합니다.하지만이 솔루션은 내 작업 데이터 집합에 너무 많은 시간이 걸립니다 (업데이트 된 답변 참조). –

5

변환 my.df하고, 다음 목록의 각 구성 요소의 부분 집합에 함수를 적용하는 것이 분할, 데이터 프레임에 강요 후 :

lapply(split(as.list(my.df), grp), function(x) rowMeans(as.data.frame(x))) 

이 제공 :

> lapply(split(as.list(my.df), grp), function(x) rowMeans(as.data.frame(x))) 
$`1` 
[1] 0.8229189 0.4901288 0.2057578 0.6531641 0.3897858 0.4225179 
[7] 0.3905410 0.3928784 0.1715857 0.3973192 

$`2` 
[1] 0.61348623 0.61229702 0.31938521 0.28325342 0.25857158 
[6] 0.49071991 0.01179999 0.57639186 0.38407240 0.17467337 
로마의 "가난한 사람의 적용"@에 해당

: 구성 요소의 이름을 제외하고

> roman <- lapply(as.list(as.numeric(levels(grp))), 
+     FUN = function(x, cn, data) { 
+      rowMeans(data[grp %in% x]) 
+     }, cn = grp, data = my.df) 
> gavin <- lapply(split(as.list(my.df), grp), 
+     function(x) rowMeans(as.data.frame(x))) 
> all.equal(roman, gavin) 
[1] "names for current but not for target" 

.

+0

이 방법은 grp 벡터가 올바른 길이가 아니라는 사실을 자동으로 무시합니다. – hadley

+0

@hadley 올바른 길이가 아닌 것은 무엇입니까? 'grp'는 길이가 4이고'as.list (my.df)'도 길이가 4입니다. 왜 이것이'split (1 : 4, grp)'과 같은 것이 아닌가요? 목록은 결국 벡터입니다. –

+0

@hadley님께 서 질문에 대한 귀하의 의견을 말씀 드렸습니다. 필요한 부분을 잘못 이해했다고 생각됩니다. –