2014-08-28 2 views
0

아래에서 설명하는 문제를 신속하고 효율적으로 처리 할 방법을 찾고 있습니다. 어떤 도움을 주셔서 감사합니다, 미리 감사드립니다!"조회"함수를 벡터화하는 올바른 방법

동일한 개체에 대해 서로 다른 정보를 가진 두 개의 매우 큰 CSV 파일이 있지만 최종 계산에는 다른 테이블의 모든 특성이 필요합니다. 나는 많은 수의 전기 변전소의 부하를 계산하려고한다. 먼저 고유 한 전기 변전소 목록을 가지고있다.

Unique_Substations <- data.frame(Name = c("SubA", "SubB", "SubC", "SubD")) 

다른 목록에는이 변전소의 고객에 대한 정보가 있습니다.

그리고 또 다른 목록에는이 고객의 지붕에 대한 정보 (다른 해에 대한)가 있습니다.

Solar_Panels <- data.frame(
    Customer = sample(1001:1010, 10, replace = TRUE), 
    SolarPanelYear1 = sample(10:20, 10, replace = TRUE), 
    SolarPanelYear2 = sample(15:20, 10, replace = TRUE) 
) 

이제 매년 각 변전소의 부하를 확인하고 싶습니다. 나는 가정용 또는 태양 전지판의 각 유형에 대해 표준화 된 가정용 부하 및 태양 전지판 부하를 가지고 있습니다.

SolarLoad <- data.frame(Load = c(0, -10, -10, 5)) 
HouseHoldLoad <- data.frame(Type1 = c(1, 3, 5, 2), Type2 = c(3, 5, 6, 1)) 

이제 이러한 목록을 일치시켜야합니다. 나는 여러 일치를 필요 match() 단 하나의 일치

을 반환 그리고 지금 우리가 내 큰 질문에 와서 (그러나 때문에 여기

ML_SubSt_Cust <- sapply(Unique_Substations$Name, 
         function(x) which(Customer_Information$SubSt_Nm %in% x == TRUE)) 

ML_Cust_SolarP <- sapply(Customer_Information$Customer, 
         function(x) which(Solar_Panels$Customer %in% x == TRUE)) 

은 (내가 which(xxx %in% x == TRUE) 방법을 사용하여 마지막에이 방법 아마 내 유일한 문제) . 나는 매년 각 변전소의 최대 부하를 계산하고 싶다.이 목적을 위해 Unique_Substations 목록을 반복하는 for 루프를 처음 작성했는데 물론 비효율적이다. 그 후 outer()을 사용하여 속도를 높이려고했지만 내 함수를 적절하게 벡터화했다고 생각하지 않는다. 최대 기능은 다음과 같다 (나는 태양 전지판 부분을 위해서만 써야한다. 간단하게);

GetMax <- function(i, Yr) { 
    max(sum(Solar_Panels[unlist(ML_Cust_SolarP[ML_SubSt_Cust[[i]]], use.names= FALSE),Yr])*SolarLoad) 
} 

이 방법이 효과적이지는 않지만 모든 다른 방법으로 수행하는 방법을 알지 못합니다.

최종 결과를 얻으려면 외부 함수를 사용하십시오. 이러한 데이터의 내 예에서

Results <- outer(1:nrow(Unique_Substations), 1:2, Vectorize(GetMax)) 

모든 프레임은 훨씬 더 큰 (40000 행 각 정도), 그래서 정말 관련된 기능의 좋은 최적화가 필요합니다. 나는 함수를 벡터화하는 방법을 생각하려고 노력했지만 그것을 해결하지 못했습니다. 어떤 도움을 주시면 감사하겠습니다.

편집 : 나는 완전히 내가 또 다른 문제가 허용 awnser을 이해 이제

. 내 실제 Customer_Information 길이가 188k 행이며 실제 내 HouseHoldLoad 길이는 53k 행입니다. 말할 필요도없이 이것은 merge()이 아닙니다. 이 문제에 대한 또 다른 해결책이 merge()을 필요로하지 않거나 너무 느린 루프를 위해 있습니까?

+0

한 가지 예로 데이터 유형이 하나뿐이기 때문에 'data.frames'가 필요하지 않습니다. 각 개체. 벡터와 행렬이면 충분합니다. 다음으로'which (foo % bar == TRUE)'보다는'which (bar == foo)'(여기서'foo'는 스칼라이고'bar'는 벡터 또는 행렬입니다. –

+1

@CarlWitthoft'which (foo % in % bar == TRUE)'는'which (bar == foo)'가 아닌'which (foo % bar) '와 동일합니다. 'bar = c (0,1)'과'foo = c (1,0)'을 취하면 그 차이는 명백합니다. 나는'foo'가 하나의 요소만을 포함하고있을 때도 사용할 수 있다는 것에 동의하지만 그것들은 동일하지 않습니다. –

+0

@JorisMeys 감사합니다 - 좋은 지적 –

답변

2

처음 : set.seed() 임의의 데이터를 생성 할 때! 이 결과에 대한 코드 앞에 set.seed(1000)을 입력했습니다.

조금 생각해 보면 merge -ing과 dplyr이 도움이 될 것 같습니다.

## Customer SubSt_Nm HouseHoldType SolarPanelYear SPYearVal 
## 1  1001  SubB    1    1  16 
## 2  1001  SubB    1    2  18 
## 3  1001  SubB    1    2  16 
## 4  1001  SubB    1    1  20 
## 5  1002  SubD    2    1  16 
## 6  1002  SubD    2    1  13 
## 7  1002  SubD    2    2  20 
## 8  1002  SubD    2    2  18 
## 9  1003  SubA    1    2  15 
## 10  1003  SubA    1    1  16 
## 11  1005  SubC    2    2  19 
## 12  1005  SubC    2    1  10 
## 13  1006  SubA    1    1  15 
## 14  1006  SubA    1    2  19 
## 15  1007  SubC    1    1  17 
## 16  1007  SubC    1    2  19 
## 17  1009  SubA    1    1  10 
## 18  1009  SubA    1    1  18 
## 19  1009  SubA    1    2  18 
## 20  1009  SubA    1    2  18 

지금 우리 단지 그룹 및 요약 :

library(dplyr) 
library(reshape2) 

HouseHoldLoad <- melt(HouseHoldLoad, value.name="Load") %>% 
    select(HouseHoldType=variable, Load) %>% 
    mutate(HouseHoldType=gsub("Type", "", HouseHoldType)) 

Solar_Panels <- melt(Solar_Panels, id.vars="Customer", 
        value.name="SPYearVal") %>% 
    select(Customer, SolarPanelYear=variable, SPYearVal) %>% 
    mutate(SolarPanelYear=gsub("SolarPanelYear", "", SolarPanelYear)) 

dat <- merge(Customer_Information, Solar_Panels, by="Customer") 

우리를 제공합니다 : 첫째, 우리는 더 나은 형태로 데이터를 얻을 수

dat %>% group_by(SubSt_Nm, SolarPanelYear) %>% 
    summarise(mx=max(sum(SPYearVal)*SolarLoad)) 

## SubSt_Nm SolarPanelYear mx 
## 1  SubA    1 295 
## 2  SubA    2 350 
## 3  SubB    1 180 
## 4  SubB    2 170 
## 5  SubC    1 135 
## 6  SubC    2 190 
## 7  SubD    1 145 
## 8  SubD    2 190 

를 사용하면 데이터 프레임 대 data.table를 사용하는 경우 40K 항목을 사용하더라도 꽤 빨라야합니다. dplyr를 설치할 수없는 사람들을 위해

UPDATE, 이것은 당신이 정말reshape2를 설치할 수없는 경우

library(reshape2) 

HouseHoldLoad <- melt(HouseHoldLoad, value.name="Load") 
colnames(HouseHoldLoad) <- c("HouseHoldType", "Load") 
HouseHoldLoad$HouseHoldType <- gsub("Type", "", HouseHoldLoad$HouseHoldType) 

Solar_Panels <- melt(Solar_Panels, id.vars="Customer", value.name="SPYearVal") 
colnames(Solar_Panels) <- c("Customer", "SolarPanelYear", "SPYearVal") 
Solar_Panels$SolarPanelYear <- gsub("SolarPanelYear", "", Solar_Panels$SolarPanelYear) 

dat <- merge(Customer_Information, Solar_Panels, by="Customer") 

rbind(by(dat, list(dat$SubSt_Nm, dat$SolarPanelYear), function(x) { 
    mx <- max(sum(x$SPYearVal) * SolarLoad) 
})) 

##  1 2 
## SubA 295 350 
## SubB 180 170 
## SubC 135 190 
## SubD 145 190 

(잘하면 그 설치입니다) reshape2를 사용하여,이 단지 기본 작동 stats 패키지 :

+0

이 답변을 주셔서 감사합니다. 그러나 어떻게 든 제 작업 컴퓨터는'dplyr' 패키지를 설치하는 데 문제가있는 것 같습니다. 또한이 스크립트는 슬프게도 패키지를 설치할 수없는 원격 서버에서 실행됩니다. dplyr 없이는이 방법이 있습니까? –

+0

나는 비슷한 상황을 다루어야했다. 대답에는 두 가지 유사한 해결책이 있습니다. 나는 어떤 타이밍도하지 않았지만, 나는 그들이 가장 빠른 것부터 가장 느린 것의 순서에 있다고 믿어야한다. 또한,'dplyr'을 사용할 수 있다면 데이터베이스 추출과 추출을 요구할 수도 있습니다 (나는 당신이 작업하고 있다고 가정하고 있습니다). – hrbrmstr

+0

그래, 정말 고마워! 나는 그것을 시험해보고 그것이 효과가있을 때 받아 들일 것이다! –

관련 문제