2017-02-05 1 views
3

의 요소의 모든 과거의 발행 수를 카운트 나는이처럼 보이는 아주 큰 dataframe (3 백만 행)이 있습니다큰 데이터 세트

df = pd.DataFrame({'user_id' : ['100','101','102','103','104'], 
      'service_id' : ['73', '73', '46', '12', '12'], 
      'date_of_service' : ['2015-06-10 17:00:00', 
           '2014-09-27 17:00:00', 
           '2015-01-12 17:00:00', 
           '2012-08-22 17:00:00', 
           '2013-03-07 17:00:00']}) 
df 

나는 사용자 ID에 대한 열이 있습니다. 사용자는 서비스를 제공하고 있으며 각 서비스는 id (service_id)를 가지고 있습니다. 각 서비스에는 날짜 (date_of_service)가 있습니다.

내가 각 행에 대해, 계산 열, 사용자가 (현재 포함) 과거에 수행 한 서비스의 수, 즉, 나는 다음과 같은 결과 dataframe 싶습니다 만들 싶습니다

df = pd.DataFrame({'user_id' : ['100','101','102','103','104'], 
      'service_id' : ['73', '73', '46', '12', '12'], 
      'date_of_service' : ['2015-06-10 17:00:00', 
           '2014-09-27 17:00:00', 
           '2015-01-12 17:00:00', 
           '2012-08-22 17:00:00', 
           '2013-03-07 17:00:00'], 
       'number_of_past_services' : [2, 1, 1, 1, 2]}) 
df 
을 내가

가 나는 GROUPBY 및 카운트 사용했던 어떤

:

df['count_services'] = df.ix[:, 1:].groupby('user_id').transform('count') 

문제가 있다는 것입니다을, 여기, 나는 전체 데이터 세트에 걸쳐 모든 사건을 계산합니다. 내가 원하는 것은 과거의 사건을 갖는 것입니다!

I는 예를 들어, SQL과 같은 동작을 이용하여 필터링하는 시도 : 첫 번째 행에 대한 좋은 결과를 제공

len(df[df.date_of_service < df['date_of_service'][0]][df.user_id == df.user_id[0]]) 

한다. 그러나이 계산은 단 한 행에 약 1 초 걸립니다!

나는 이것을 효율적으로 만드는 방법을 알고 싶습니다.

답변

2

IIUC 당신은이 방법을 수행 할 수 있습니다

In [69]: df['number_of_past_services'] = df.sort_values('date_of_service') \ 
              .assign(x=1) \ 
              .groupby('service_id')['x'].cumsum() 

In [70]: df 
Out[70]: 
     date_of_service service_id user_id number_of_past_services 
0 2015-06-10 17:00:00   73  100      2 
1 2014-09-27 17:00:00   73  101      1 
2 2015-01-12 17:00:00   46  102      1 
3 2012-08-22 17:00:00   12  103      1 
4 2013-03-07 17:00:00   12  104      2 
+0

그것은 작동한다! 고마워요! –

+0

@PeterMartigny, 여러분은 환영합니다. 질문에 대답했다고 생각되면 [accepting] (http://meta.stackexchange.com/a/5235) 답을 생각하십시오. – MaxU

0

내가 제대로 이해하면, 당신은 할 수 :

  • past_occurences.get(user_id, 0) : date_of_service
  • 에 의해

    • 종류의 데이터가 과거의 발행 수있는 모든 정렬 된 행을 통해
    • 으로 반복의 빈 사전을 만들 필요한 정보를 보유하고 있습니다.
    • past_occurences[user_id] = past_occurences.get(user_id, 0) + 1은 dictionar 와이. 모든 단계의

, 정렬은 가장 느린 것입니다. 나머지는 합리적으로 빠릅니다.

추신 : defaultdict을 사용할 수도 있습니다. 여기 example입니다.