2013-10-02 3 views
2

나는 팬더로 분석하려고하는 MySQL 데이터베이스에 음악 태깅 데이터의 큰 데이터 세트를 가지고 있습니다. MySQL에서 .tsv로 내 보낸 다음 분석을위한 데이터 프레임으로 읽습니다.팬더의 여러 레벨을 평균합니다.

데이터의 각 행은 지정된 사용자 (숫자 사용자 ID로 표시)가 특정 시간에 특정 태그 (여기서는 숫자 ID로 표시)를 태그 지정했다는 것을 나타내는 튜플입니다. 어떤 인덱스 그래서 데이터의 샘플은 다음과 같이 보일 것이다 :

 uid artist tag  date 
0 2096963  559 46 2005-07-01 
1 2096963  584 1053 2005-07-01 
2 2096963  584 2044 2005-07-01 
3 2096963  584 2713 2005-07-01 
4 2096963  596 236 2005-07-01 
... 
     uid artist tag  date 
99995 2656262 8095 57 2005-08-01 
99996 2656262 8095 79 2005-08-01 
99997 2656262 8095 4049 2005-08-01 
99998 2656262 8095 8290 2005-08-01 
99999 2610168 8095 1054 2005-08-01 

는 분석을 용이하게하기 위해, 나는 모든 색인 및 더미 주석 변수 추가 (하나의 인스턴스를 태그 나타내는 데이터의 각 행을, 또는 주석) 한 . 그래서 지금 우리가이 같은 형식의 데이터로

data = pd.read_table(filename,header=None, names=('uid','artist','tag','date'), index_col=['date','uid','artist','tag'], parse_dates='date') 
data['annotations'] = 1 

In [41]: data.head() 
Out[41]: 
           annotations 
date  uid  artist tag 
2005-07-01 2096963 559 46    1 
        584 1053   1 
          2044   1 
          2713   1 
        596 236    1 
... 

를, 그것은 간단한 주파수 분포를 계산하는 사소한입니다. 마찬가지로

data.sum(level='uid').sort('anno',ascending=False) 

, 나는 맞은 편 (매달 주석의 총 수를 확인할 수 있습니다 내가 (. 주파수 내림차순) 각 사용자가 무언가를 태그 횟수를 결정하려는 경우 예를 들어, 그것만큼 간단합니다 모든 사용자 및 태그) :

data.sum(level='date') 

그러나 더 복잡한 계산에 문제가 있습니다. 특히, 매월 사용자 당 평균 주석 수를 원한다면 어떻게해야합니까? 나는 호출하는 경우 :

data.sum(level=['date','uid']).head() 

나는 매달 사용자 당 주석의 번호를, 즉 :

    anno 
date  uid 
2005-07-01 1040740 10 
      1067454 23 
      2096963 136 
      2115894  1 
      2163842  4 
... 

하지만 사용자를 통해 그 값의 월 평균 얻을 수있는 간단한 방법은 무엇입니까? 즉, 매월 "사용자 수"열의 평균 사용자 수는 얼마입니까? 이처럼 다양한 메트릭을 계산할 수 있으므로 솔루션이 일반화되기를 바랍니다.

답변

1

나는 내 원래 다중 색인 형식에 맞는 다른 방법을 생각하고, 나는이 @DanAllan에 의해 제안 된 방법보다 더 빨리 생각 .

월별 사용자 별 평균 주석을 계산한다는 것을 상기하면서 데이터 프레임 두 개를 작성해 봅시다 (여기서 데이터의 서브 세트 만 사용하므로 nrows 인수). DATA1 더미 변수 다중 인덱스 버전이고, DATA2 프로세스 인 인덱싱되지 않은 (DATA2) 버전으로 @DanAllan

indexes=['date','uid','artist','iid','tag'] 
data1 = pd.read_table(filename,header=None, nrows=1000000, names=('uid','iid','artist','tag','date'),index_col=indexes, parse_dates='date') 
data['anno']=1 
data2 = pd.read_table(filename,header=None, nrows=1000000, names=('uid','iid','artist','tag','date'), parse_dates='date') 

제안한 인덱싱되지 않은 버전 : 멀티와

daily_users = data2.groupby('date').uid.nunique() 
daily_annotations = data2.groupby('date').count().uid 
anno_per_user_perday2 = daily_annotations/daily_users.map(float) 

인덱스 버전 (DATA1)은, 우리가 할 수

anno_per_user_perday = data1.sum(level=['date','uid']).mean(level='date').anno 

를 결과는 동일하지만, 전체 50 마일의 성능이 더 큰 문제가 될 것입니다 (인덱스 버전보다 세 배 이상 빠른 속도 더 llion 행 데이터 세트) :

%timeit -n100 daily_users = data2.groupby('date').uid.nunique() ; daily_annotations = data2.groupby('date').count().uid ; anno_per_user_perday2 = daily_annotations/daily_users.map(float) 
100 loops, best of 3: 387 ms per loop 

%timeit -n100 anno_per_user_perday1 = data1.sum(level=['date','uid']).mean(level='date').anno 
100 loops, best of 3: 149 ms per loop 

dataframe 생성은 인덱스 버전으로 느리지 만, 그것은 준다 유연성 가치가 보인다.

2

큰 멀티 인덱스는 번거롭 수 있습니다. 더미 열 '특수 효과'를 버리고 sum 대신 count을 사용하는 것이 좋습니다.

data.groupby('date').count() 
: 1 일 기준, 총 주석으로

data.groupby('uid').count().sort(ascending=False) 

:

pd.read_table(filename,header=None, names=['uid','artist','tag','date'], parse_dates='date') 

각 사용자의 주석을 계산하기 위해, 즉, 인덱스를 지정하지 않고 데이터를 읽기 시작하려면

매일 순 사용자 수 :

총 주석으로

daily_users = data.groupby('date').uid.nunique() 
매일 : 사용자 당

daily_annotations = data.groupby('date').count() 

일일 평균 주석은 사용자의 수를 그 날 나눈 단지 매일 총 주석이다. groupby 작업의 결과로이 두 시리즈는 모두 날짜별로 인덱싱되므로 자동으로 정렬됩니다.사용자에서 한 달에 평균 주석으로

mean_daily_annotations_per_user = daily_annotations/daily_users 

, 서로 다른 시간 주파수에 의해 그룹화 resample, 좋은 기능을 사용하는 것이 가장 편리합니다.

mean_monthly_annotations_per_user = mean_daily_anootations_per_user.resample('M') 
+0

처음부터 리샘플링을 시도해보고 싶었지만 작동하지 않는 것 같습니다 (적어도 어떻게 설명했는지는 아닙니다). '날짜'를 색인으로 사용하면 '평균'을 사용하여 다시 샘플링하면 사용자 당 평균 주석 수가 아니라 매월 아티스트, 태그 및 사용자의 모든 숫자 ID (의미가 없음)의 산술 평균이 계산됩니다. 반면에 '백작'은 매월 행의 총 수를 제공하며 잘못된 값입니다. 사용자 당 평균 매수 (행)가 필요합니다. – moustachio

+0

나는 처음에 당신의 질문을 오해했기 때문에 이것을 편집 해왔다. 다시 읽으십시오. 나는 지금 당장 얻은 것 같아. –

+0

훨씬 더 좋지만 유일한 문제는 daily_annotations의 정의가 특정 열을 꺼내야한다는 것입니다. 그렇지 않으면 division을 할 수 없습니다. (daily_annotations는 데이터 프레임이지만 daily_users는 시리즈입니다.) 임의의 어떤 열을 선택했는지 알 수 있듯이 대답 편집 및 수락 – moustachio