2017-10-06 31 views
1
나는 삼십일 시계열 창에 다시 샘플링하고자하는 다음과 같은 일반적인 형식의 데이터가

:파이썬 팬더 : 리샘플링 다변량 시계열 GROUPBY와

'customer_id','transaction_dt','product','price','units' 
1,2004-01-02,thing1,25,47 
1,2004-01-17,thing2,150,8 
2,2004-01-29,thing2,150,25 
3,2017-07-15,thing3,55,17 
3,2016-05-12,thing3,55,47 
4,2012-02-23,thing2,150,22 
4,2009-10-10,thing1,25,12 
4,2014-04-04,thing2,150,2 
5,2008-07-09,thing2,150,43 

내가 시작하는 30 일 개 창을 싶습니다을 2014-01-01 년 12 월 31 일부터 2018 년 12 월 31 일까지 모든 고객이 모든 창에 기록을 보유 할 것이라는 보장은 없습니다. 고객이 창에 여러 트랜잭션을 가지고있는 경우 가격의 가중 평균을 취하여 단위를 합산하고 제품 이름을 연결하여 고객 당 창 하나당 하나의 레코드를 만듭니다. 누구든지이 문제를 접근하는 더 좋은 방법을 알고

wa = lambda x:np.average(x, weights=df.loc[x.index, 'units']) 
con = lambda x: '/'.join(x)) 

agg_funcs = {'customer_id':'first', 
      'product':'con', 
      'price':'wa', 
      'transaction_dt':'first', 
      'units':'sum'} 

df_window = df.groupby(['customer_id', pd.Grouper(freq='30D')]).agg(agg_funcs) 
df_window_final = df_window.unstack('customer_id', fill_value=0) 

경우, 나는 그것을 감사하겠습니다 (특히에 장소 및/또는 벡터화의 메소드와) : 나는 지금까지 무엇을 가지고

이 같은 것입니다. 이상적으로는 창 시작 및 종료 날짜를 행에 열로 추가하는 것도 좋습니다.

최종 출력이 이상적과 같습니다

'customer_id','transaction_dt','product','price','units','window_start_dt','window_end_dt' 
1,2004-01-02,thing1/thing2,(weighted average price),(total units),(window_start_dt),(window_end_dt) 
2,2004-01-29,thing2,(weighted average price),(total units),(window_start_dt),(window_end_dt) 
3,2017-07-15,thing3,(weighted average price),(total units),(window_start_dt),(window_end_dt) 
3,2016-05-12,thing3,(weighted average price),(total units),(window_start_dt),(window_end_dt) 
4,2012-02-23,thing2,(weighted average price),(total units),(window_start_dt),(window_end_dt) 
4,2009-10-10,thing1,(weighted average price),(total units),(window_start_dt),(window_end_dt) 
4,2014-04-04,thing2,(weighted average price),(total units),(window_start_dt),(window_end_dt) 
5,2008-07-09,thing2,(weighted average price),(total units),(window_start_dt),(window_end_dt) 
+0

가중 평균 가격과 평균의 무게를 필요로한다. 무게는 얼마입니까? 그리고 모호함이 없도록 최종 결과는 어떻게 보이게되어 도움을주기로 결정한 사람들은 답을 제출하기 전에 비교할 것이 있습니다. – piRSquared

+0

죄송합니다. 혼란 스럽다면 groupby 동안 창에있는 총 단위 수에서 가중 평균 가격을 계산해야합니다. wa = lambda x : np.average (x, weights = df.loc [x.index , 'units']) – Pylander

+0

가격의 무게는 (of) 단위입니다. – Pylander

답변

1

편집을 새로운 솔루션을. 나는 각각 transaction_dt을 30 일의 기간 개체로 변환 한 다음 그룹화를 수행 할 수 있다고 생각합니다.

p = pd.period_range('2004-1-1', '12-31-2018',freq='30D') 
def find_period(v): 
    p_idx = np.argmax(v < p.end_time) 
    return p[p_idx] 
df['period'] = df['transaction_dt'].apply(find_period) 
df 

    customer_id transaction_dt product price units  period 
0   1  2004-01-02 thing1  25  47 2004-01-01 
1   1  2004-01-17 thing2 150  8 2004-01-01 
2   2  2004-01-29 thing2 150  25 2004-01-01 
3   3  2017-07-15 thing3  55  17 2017-06-21 
4   3  2016-05-12 thing3  55  47 2016-04-27 
5   4  2012-02-23 thing2 150  22 2012-02-18 
6   4  2009-10-10 thing1  25  12 2009-10-01 
7   4  2014-04-04 thing2 150  2 2014-03-09 
8   5  2008-07-09 thing2 150  43 2008-07-08 

이제이 데이터 프레임을 사용하여 제품의 연결, 가격의 가중 평균 및 단위 합계를 얻을 수 있습니다. 그런 다음 기간 기능을 사용하여 종료 시간을 가져옵니다.

def my_funcs(df): 
    data = {} 
    data['product'] = '/'.join(df['product'].tolist()) 
    data['units'] = df.units.sum() 
    data['price'] = np.average(df['price'], weights=df['units']) 
    data['transaction_dt'] = df['transaction_dt'].iloc[0] 
    data['window_start_time'] = df['period'].iloc[0].start_time 
    data['window_end_time'] = df['period'].iloc[0].end_time 
    return pd.Series(data, index=['transaction_dt', 'product', 'price','units', 
            'window_start_time', 'window_end_time']) 

df.groupby(['customer_id', 'period']).apply(my_funcs).reset_index('period', drop=True) 

enter image description here

+0

이것은 매우 우아한 해결책입니다! 고맙습니다! 독자들에게 일련의 groupby/transforms을 사용하여 새로운 값을 생성 한 다음 최종 그룹을 생성하는 방법을 생각해 냈습니다. – Pylander

+0

최근에 다시 방문했습니다. 불행히도, 'window_start_time'과 'window_end_time'이 제대로 작동하는지 모르겠습니다. 저를위한 마지막 30 일 창 날짜 만 돌려 보내는 것을 보인다. – Pylander

관련 문제