2016-07-25 4 views
2

dataframe의 행의 부분 집합에 요약 :가입하고 내가 날짜 범위와 일부 관련 colums 저장하는 팬더 dataframe이

 date_start date_end ... lots of other columns ... 
1  2016-07-01 2016-07-02 
2  2016-07-01 2016-07-03 
3  2016-07-01 2016-07-04 
4  2016-07-02 2016-07-07 
5  2016-07-05 2016-07-06 

와 날짜에 의해 색인 마리오 목격의 또 다른 dataframe :

   pikachu_sightings 
     date 
2016-07-01     2 
2016-07-02     4 
2016-07-03     6 
2016-07-04     8 
2016-07-05     10 
2016-07-06     12 
2016-07-07     14 

첫 번째 df의 각 행에 해당 날짜 범위 (즉, date_start에서 date_end까지)의 pikachu_sightings 합계를 계산하여이를 새 열에 저장하고 싶습니다. 그래서 이런 DF로 끝날 것이다 (숫자는 명확하게하기 위해에서 왼쪽) :

 date_start date_end total_pikachu_sightings 
1  2016-07-01 2016-07-02      2 + 4 
2  2016-07-01 2016-07-03     2 + 4 + 6 
3  2016-07-01 2016-07-04    2 + 4 + 6 + 8 
4  2016-07-02 2016-07-07 4 + 6 + 8 + 10 + 12 + 14 
5  2016-07-05 2016-07-06     10 + 12 

나는 반복적으로 내가 날짜 범위의 테이블의 각 행을 반복 것이 일을 한 경우, 행의 서브 세트를 선택 이 팬더를 사용하여 나의 시도는

for range in ranges.itertuples(): 
    sightings_in_range = sightings[(sightings.index >= range.date_start) & (sightings.index <= range.date_end)] 
    sum_sightings_in_range = sightings_in_range["pikachu_sightings"].sum() 
    ranges.set_value(range.Index, 'total_pikachu_sightings', sum_sightings_in_range) 

하지만 두 dataframes의 길이 때문에 실패하지만이 방법은 내 데이터 세트에 대한 너무 느립니다 - 날짜 범위를 일치시키고 그 위에 합을 수행 목격의 테이블 는 일치하지 않습니다. (그렇다고해도 내 방식에는 다른 결함이있을 수 있습니다.)

range["total_pikachu_sightings"] = 
    sightings[(sightings.index >= range.date_start) & (sightings.index <= range.date_end) 
      ["pikachu_sightings"].sum() 

일반적인 접근 방식/디자인이 다른 기능과 통합되기를 원한다는 점을 이해하기 위해 노력하고 있습니다. sum은 예제로는 가장 쉬운 것처럼 보입니다. 이것이 명백한 질문이라면 미안 해요 - 저는 팬더를 처음 사용합니다!

답변

1

먼저 pikachu_sightings에 datetime 인덱스가 있고 정렬되어 있는지 확인하십시오.

p = pikachu_sightings.squeeze() # force into a series 
p.index = pd.to_datetime(p.index) 
p = p.sort_index() 

는 그런 다음 date_startdate_end이 날짜되어 있는지 확인합니다.

df.date_start = pd.to_datetime(df.date_start) 
df.date_end = pd.to_datetime(df.date_end) 

다음은 단순히

df.apply(lambda x: p[x.date_start:x.date_end].sum(), axis=1) 

0  6 
1 12 
2 20 
3 54 
4 22 
dtype: int64 
+0

감사합니다. 우아한 해결책이며 작동합니다.마지막 줄에있는 코드가 여전히 팬더를 사용하고 있습니까? 나는 대용량 데이터 세트 (pukachu_sightings에서 50,000 개의 날짜 범위와 6000 개의 행에 대해 30 초 - 훨씬 더 큰 데이터 세트를 처리하려고하는데 30 초)가 매우 느리기 때문에 묻습니다. – Matt

+0

@Matt 그것은 팬다입니다. 벡터화되지 않았습니다. – piRSquared

2

벡터화 솔루션의 스케치 :

시작합니다 p와 piRSquared의 대답에있다.

은 : 있는지 date_ COLS는 datetime64 dtypes이 즉를 확인

df['date_start'] = pd.to_datetime(df.date_time) 

그런 다음 누적 합계를 계산 :

psums = p.cumsum() 

result = psums.asof(df.date_end) - psums.asof(df.date_start) 

그건 아직 말을하지만. asof은 마지막으로 좋은 값을 반환하기 때문에 때로는 정확한 시작 날짜와 때로는 (데이터에 따라) 걸릴 수 있습니다. 그래서, 당신은 그것을 조정해야합니다. 날짜 빈도가 day 인 경우 -pd.Timedelta(1, 'h')과 같이 p의 색인을 뒤로 이동 한 다음 p.asof(df.start_date)을 추가하는 것이 좋습니다.

관련 문제