2010-07-26 4 views
28

많은 행과 많은 열이있는 데이터 프레임이 있다고 가정합니다.R에서는 데이터 프레임의 행을 실제로 빠르게 돌릴 수 있습니까?

열의 이름이 있습니다. 번호로 행에 액세스하고 이름으로 열에 액세스하려고합니다.

예를 들어, 행 돌이 하나 (아마도 느린) 방법은

for (i in 1:nrow(df)) { 
    print(df[i, "column1"]) 
    # do more things with the data frame... 
} 

또 다른 방법은 별도의 열에 대한 "목록"(column1_list = df[["column1"] 등)을 생성하고, 하나 개의 루프에서 목록에 액세스하는 것입니다. 이 방법은 빠르지 만 많은 열에 액세스하려는 경우 불편합니다.

데이터 프레임의 행을 빠르게 순환시키는 방법이 있습니까? 다른 데이터 구조가 반복 루핑에 더 좋습니까?

+1

df [, "column1"]과 어떻게 다른가요? 또한? margin = 1을 적용하십시오. – Greg

+0

예제는 내가 실제로하고 싶지 않은 것이 었습니다. 데이터 프레임에 자바 스크립트 파일의 데이터로 값을 쓰고 싶었습니다. "적용"의 "여백"에 대한 정보는 +1. –

+0

특정 상황에서 열의 값을 중심으로 이동하려면 행을 반복해야했습니다. 나는 R에서 이것을하는 더 좋은 방법이 있음을 상기시켰다 : http://stackoverflow.com/questions/7746567/how-to-swap-values-between-2-columns – thadk

답변

13

의견을 찾기가 더 어려워서 이미 이것에 대한 의견을 잃어 버렸기 때문에 완전한 대답을해야한다고 생각합니다. nullglob의 예가 있습니다. 차이점을 보여주고 가족 기능을 많이 적용합니다. 다른 예제보다 더 좋습니다. 하나가 매우 느린 것과 같은 기능을 만들 때 그것은 모든 속도가 소비되는 곳이며 루핑상의 차이점을 찾지 못할 것입니다. 그러나 함수를 사소한 것으로 만들면 반복이 루프에 얼마나 영향을 미치는지 알 수 있습니다.

또한 다른 예제에서 미개척 된 적용 제품군의 일부 구성원은 흥미로운 성능 특성을 갖고 있다고 덧붙이고 싶습니다. 먼저 nullglob의 상대 결과에 대한 복제를 내 컴퓨터에 표시합니다.

n <- 1e6 
system.time(for(i in 1:n) sinI[i] <- sin(i)) 
    user system elapsed 
5.721 0.028 5.712 

lapply runs much faster for the same result 
system.time(sinI <- lapply(1:n,sin)) 
    user system elapsed 
    1.353 0.012 1.361 

그는 또한 sapply를 훨씬 느리게 발견했습니다. 테스트되지 않은 다른 것들도 있습니다. 이전 일반 데이터의 매트릭스에 적용 버전

는 ...

mat <- matrix(1:n,ncol =1),1,sin) 
system.time(sinI <- apply(mat,1,sin)) 
    user system elapsed 
    8.478 0.116 8.531 

그래서, 적용() 명령 자체는 for 루프보다 실질적으로 느리다. 내가 죄 (매트 [전, 1]).

다른 게시물에서 테스트하지 않는 것 또 하나는 tapply 인을 사용하는 경우 (루프 상당히 둔화되지 않습니다. 물론

system.time(sinI <- tapply(1:n, 1:n, sin)) 
    user system elapsed 
12.908 0.266 13.589 

, 한 사람은 이런 식으로 사용하지 않을 것이고, 대부분의 경우 그러한 속도 문제를 훨씬 능가하는 유틸리티 일 것입니다.

+1

+1입니다. 그의 게시물은 Uwe Ligges와 John Fox의 "R News"(2008 년 5 월)에서 "이 루프를 피하거나 빨리 만들 수 있습니까?"라는 기사에 대한 참조가 있습니다. 적용 기능에 대해 작성해 주셔서 감사합니다. –

11

가장 빠른 방법은이 아닌 입니다 (즉, 벡터화 된 연산). 반복해야하는 유일한 인스턴스 중 하나는 종속성이있는 경우입니다 (예 : 하나의 반복이 다른 반복에 종속 됨). 그렇지 않으면 가능한 한 루프 외부에서 많은 벡터화 된 계산을 수행하십시오.

당신이 다음 for 루프를 사용하여, 루프 필요성을 경우 다른 아무것도 (lapply 조금 빠를 수 있지만, other apply functions tend to be around the same speed as for)로 빠른 본질적이다.

+1

아마 루프를 피할 방법이 없다. 내가하고 싶었던 것 - 위의 그렉의 의견에 대한 나의 반응을 보라. –

+1

"같은 속도로"? 모든 대답을 읽었습니까? 거기에 내 대답은, 그 vapply를 사용하여 그 루프에 비해 3 배 빠른 (그 예를 들어) 보여줍니다 ... – Tommy

+2

알고리즘 효율성 측면에서, 그들은 매우 비슷한 속도 : [알고리즘 효율] (http : // en .wikipedia.org/wiki/Algorithmic_efficiency) – Toby

0

data.frames는 본질적으로 열 벡터의 목록이라는 사실을 이용하여 do.call을 사용하여 함수를 적용 할 수 있습니다 data.frame의 각 열에 대한 열 수 (다른 언어의 목록에 대한 "지퍼 링"과 유사 함)와 일치해야합니다.

do.call(paste, data.frame(x=c(1,2), z=c("a","b"), z=c(5,6))) 
+0

하지만 그건 루핑되지 않습니다. –

관련 문제