2013-10-02 96 views
2

我有一個龐大的音樂標記數據在MySQL數據庫中的數據集,我試圖用大熊貓進行分析。我將它從MySQL導出到.tsv文件,然後將其作爲數據框讀入以供分析。平均在熊貓的不同級別

數據中的每一行都是一個元組,指示特定用戶(由數字用戶標識表示)在特定時間用特定標籤(在此表示爲數字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 
... 

但什麼是一個簡單的方法,然後獲取這些值的跨用戶每月平均?也就是說,對於每個月,「anno」列的用戶平均數是多少?我有我想要計算的各種指標,所以我希望解決方案能夠推廣。

回答

1

我想通了,適合我原來的多指數格式的另一種方法,我覺得比@DanAllan提出的方法要快。我們回顧一下,我們正在計算每個用戶每月的平均註釋,讓我們構建兩個數據框(我只用了這裏的一部分數據,因此是nrows參數)。 DATA1是多指數版本與虛擬變量,和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') 

隨着未加索引(DATA2)版本的版本未加索引的過程是:

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

隨着多索引版本(數據1),我們可以這樣做:

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 

生成數據幀的索引版本比較慢,但它提供的靈活性似乎值得。

2

Big MultiIndexes可能很麻煩。我建議放棄你的虛擬列,'註釋',並使用count而不是sum

首先,在數據讀取方面沒有分配指標,即

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

要計算每個用戶的註釋:

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

每天總註釋:

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

每天統計獨特用戶數:

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

我想從一開始就嘗試重新採樣,但它似乎不起作用(至少不是你如何描述)。以'date'作爲索引,重新採樣'mean'只是計算藝術家,標籤和用戶每個月的所有數字ID的算術平均值(這是沒有意義的),而不是每個用戶的平均註釋數量。另一方面,'計數'給出了每個月的總行數,這也是錯誤的。我需要每個用戶每個月的平均註釋數(行)。 – moustachio

+0

我一直在編輯這個,因爲我最初誤解了你的問題。請再讀一遍。我想我現在已經明白了。 –

+0

好得多,但唯一的問題是daily_annotations的定義需要抽出一個特定的列,否則你不能進行分割(如你所定義的那樣,daily_annotations是一個數據框,但daily_users是一個系列。任意選擇哪一列,據我所知,編輯並接受答案 – moustachio