2016-03-23 18 views
0

我有熊貓一個數據幀,看起來像這樣:如何檢查熊貓中另一個數組中存在的數組中的值的百分比?

app_id_x period app_id_y 
10 [pb6uhl15, xn66n2cr, e68t39yp, s7xun0k1, wab2z... 2015-19 NaN 
11 [uscm6kkb, tja4ma8u, qcwhw33w, ux5bbkjz, mmt3s... 2015-20 NaN 
12 [txdbauhy, dib24pab, xt69u57g, n9e6a6ol, d9f7m... 2015-21 NaN 
13 [21c2b5ca5e7066141b2e2aea35d7253b3b8cce11, oht... 2015-22 [g8m4lecv, uyhsx6lo, u9ue1zzo, kw06m3f5, wvqhq... 
14 [64lbiaw3, jum7l6yd, a5d00f6aba8f1505ff22bc1fb... 2015-23 [608a223c57e1174fc64775dd2fd8cda387cc4a47, ze4... 
15 [gcg8nc8k, jkrelo7v, g9wqigbc, n806bjdu, piqgv... 2015-24 [kz8udlea, zwqo7j8w, 6d02c9d74b662369dc6c53ccc... 
16 [uc311krx, wpd7gm75, am8p0spd, q64dcnlm, idosz... 2015-25 [fgs0qhtf, awkcmpns, e0iraf3a, oht91x5j, mv4uo... 
17 [wilhuu0x, b51xiu51, ezt7goqr, qj6w7jh6, pkzkv... 2015-26 [zwqo7j8w, dzdfiof5, phwoy1ea, e7hfx7mu, 40fdd... 
18 [xn43bho3, uwtjxy6u, ed65xcuj, ejbgjh61, hbvzt... 2015-27 [ze4rr0vi, kw06m3f5, be532399ca86c053fb0a69d13... 

我想做的事,是每個period,這是行,檢查這也在名單app_id_y值% app_id_x值,例如,該行如果ze4rr0vi和gm83klja不到app_id_x其中包含該行53個值,那麼就應該有一個叫adoption_rate新列是:

period adoption_rate 
2015-9  0% 
2015-22  3.56% 
2015-25  4.56% 
2015-26  5.10% 
2015-35  4.58% 
2015-36  1.23% 
+0

我認爲你可以使用更好的樣本並添加樣本的所需輸出。也許幫忙 - 'print pd.DataFrame({'app_id_x':{10:['pb6uhl15','pb6uhl15','pb6uhl15'],11:['pb6uhl15','pb6uhl15','e68t39yp','s7xun0k1'] ,12:['pb6uhl15','s7xun0k1'],13:['s7xun0k1'],14:['pb6uhl15','pb6uhl15','e68t39yp','s7xun0k1']},'app_id_y':{10: 'pb6uhl15'],11:['pb6uhl15'],12:np.nan,13:['e68t39yp','xn66n2cr'] ['e68t39yp','xn66n2cr'] },'period':{10:'2015-19',11:'2015-20',12:'2015-21',13:'2015-22',14:'2015-23'}})'隨意修改它以獲得更好的效果。祝你好運。 – jezrael

回答

1

您可以使用numpy.intersect1d獲取兩個數組之間的通用元素,這需要完成大部分工作。爲了得到輸出,我將編寫一個函數來獲取給定行的重疊百分比,然後使用apply來添加adoptive_rate列。

def get_overlap_pcnt(row): 
    # Get the overlap between arrays. 
    overlap = len(np.intersect1d(row['app_id_x'], row['app_id_y'])) 

    # Compute the percent common. 
    if overlap == 0: 
     pcnt = 0 
    else: 
     pcnt = 100*overlap/len(row['app_id_y']) 

    return '{:.2f}%'.format(pcnt) 

df['adoption_rate'] = df.apply(get_overlap_pcnt, axis=1) 

我不能完全從,如果你想app_id_yapp_id_x爲分母你的問題告訴,但是這是一個很容易的改變作出。以下是使用我創建的一些示例數據的示例輸出。

   app_id_x   app_id_y period adoption_rate 
0 [a, b, c, d, e, f, g]    NaN 2015-08   0.00% 
1    [b, c, d]  [b, c, d, e] 2015-09  75.00% 
2  [a, b, c, x, y, z]  [x, y, z] 2015-10  100.00% 
3  [q, w, e, r, t, y] [a, b, c, d, e] 2015-11  20.00% 
4    [x, y, z]  [a, b, x] 2015-12  33.33% 
+0

我喜歡這個解決方案。使用'np.intersect1d'而不是'set'有沒有好處? – exp1orer

+0

我還沒有計時,但我懷疑'np.intersect1d'對大數據集有更好的性能,因爲它利用了numpy的底層C/C++/Fortran代碼。 – root

1

如何:

df[adoption_rate] = [100.*len(set(df.loc[i,app_id_x]) &\ 
        set(df.loc[i,app_id_y]))/len(set(df.loc[i,app_id_x]))\ 
        if type(df.loc[i,app_id_x])==list and \ 
        type(df.loc[i,app_id_x])==list \ 
        else 0. for i in df.index] 

編輯:固定的任何數組中重複值的情況。

0

其他答案缺失的是這是一種非常不自然的方式來存儲您的數據。一般來說,pandas DataFrame中的值應該是標量。

爲了解決此問題,更好地表示數據的方法是將它們重新整形爲兩個數據框X和Y.在X中,行是句點,列是標識(例如'g8m4lecv')。 X數據框中的條目爲1,如果該值在該時段的X列中,則類似地爲Y.

這使您可以更輕鬆地執行您想要執行的操作。

這裏所說:

import pandas as pd 
import numpy as np 


# from the comment by @jezrael . Super useful, thanks 
df = pd.DataFrame({'app_id_x': {10: ['pb6uhl15', 'pb6uhl15', 'pb6uhl15'], 11: ['pb6uhl15', 'pb6uhl15', 'e68t39yp', 's7xun0k1'], 12: [ 'pb6uhl15', 's7xun0k1'], 13: [ 's7xun0k1'], 14: ['pb6uhl15', 'pb6uhl15', 'e68t39yp', 's7xun0k1']}, 'app_id_y': {10: ['pb6uhl15'], 11: ['pb6uhl15'], 12: np.nan, 13: ['pb6uhl15', 'xn66n2cr', 'e68t39yp', 's7xun0k1'], 14: ['e68t39yp', 'xn66n2cr']}, 'period': {10: '2015-19', 11: '2015-20', 12: '2015-21', 13: '2015-22', 14: '2015-23'}}) 


# pulling the data out of the lists in the starting dataframe 
new_data = [] 
for _,row in df.iterrows(): 
    for col in ['app_id_x','app_id_y']: 
     vals = row[col] 
     if isinstance(vals,list): 
      for v in set(vals): 
       new_data.append((row['period'],col[-1],v,1)) 

new_df = pd.DataFrame(new_data, columns = ['period','which_app','val','exists']) 

# splitting the data into two frames 
def get_one_group(app_id): 
    return new_df.groupby('which_app').get_group(app_id).drop('which_app', axis=1) 

X = get_one_group('x') 
Y = get_one_group('y') 


# converting to the desired format 
def convert_to_indicator_matrix(df): 
    return df.set_index(['period','val']).unstack('val').fillna(0) 

X = convert_to_indicator_matrix(X) 
Y = convert_to_indicator_matrix(Y) 

現在,它的超級容易真正解決您的問題。我不清楚你需要解決什麼問題,但是假設你想知道每個時期的number_ids_in_both除以number_ids_in_Y

combined = (X * Y).fillna(0) 
combined.sum(axis=1)/Y.sum(axis=1) 
相關問題