2016-11-14 13 views
3

我格式化爲這樣的「查找」表:查找值

Min | Max | Val 
    1 | 99 | "Principal" 
100 | 199 | "Partner" 
... | ... | ... 

有一個CURRENT_POINTS一系列在我據幀是MIN或MAX(含)之間。

問題:如何創建基於上述查找表的VAL列?我最初的想法是使用df.lookup,但在df中有800K行,所以這兩個表的大小並不相同。

在此先感謝您的幫助!

有什麼想法?

回答

3

我會用cut()的方法。

假設你有以下的DF:

In [187]: lkp 
Out[187]: 
    Min Max Val 
0 1 99 AAA 
1 100 199 BBB 
2 200 299 CCC 
3 300 399 DDD 

In [188]: df 
Out[188]: 
    CURRENT_POINTS 
0    55 
1    10 
2    20 
3    144 
4    194 
5    143 
6    397 
7    233 
8    128 
9    215 

使用cut()方法,我們可以生產出category D型的新列,這可能會節省大量的內存:

In [189]: df['Val'] = pd.cut(df.CURRENT_POINTS, 
    ...:     bins=[0] + lkp[['Min','Max']].stack()[1::2].tolist(), 
    ...:     labels=lkp.Val.tolist()) 
    ...: 

In [190]: df 
Out[190]: 
    CURRENT_POINTS Val 
0    55 AAA 
1    10 AAA 
2    20 AAA 
3    144 BBB 
4    194 BBB 
5    143 BBB 
6    397 DDD 
7    233 CCC 
8    128 BBB 
9    215 CCC 

In [191]: df.dtypes 
Out[191]: 
CURRENT_POINTS  int32 
Val    category 
dtype: object 

類別D型可節省大量的內存:

In [192]: big = pd.concat([df] * 10**5, ignore_index=True) 

In [193]: big.shape 
Out[193]: (1000000, 2) 

In [194]: big['str_col'] = 'AAA' 

In [198]: big.dtypes 
Out[198]: 
CURRENT_POINTS  int32 
Val    category 
str_col    object 
dtype: object 

In [195]: big.memory_usage() 
Out[195]: 
Index     80 
CURRENT_POINTS 4000000 
Val    1000032  # <--- `category` column takes 1 byte per row (plus 32 bytes overhead) 
str_col   8000000 

In [197]: big.head() 
Out[197]: 
    CURRENT_POINTS Val str_col 
0    55 AAA  AAA 
1    10 AAA  AAA 
2    20 AAA  AAA 
3    144 BBB  AAA 
4    194 BBB  AAA 

注意:在內存使用情況categoryVal注意,爲str_col列(D型:object

說明:

箱:

In [199]: lkp[['Min','Max']] 
Out[199]: 
    Min Max 
0 1 99 
1 100 199 
2 200 299 
3 300 399 

In [200]: lkp[['Min','Max']].stack() 
Out[200]: 
0 Min  1 
    Max  99 
1 Min 100 
    Max 199 
2 Min 200 
    Max 299 
3 Min 300 
    Max 399 
dtype: int64 

In [201]: lkp[['Min','Max']].stack()[1::2].tolist() 
Out[201]: [99, 199, 299, 399] 

In [202]: [0] + lkp[['Min','Max']].stack()[1::2].tolist() 
Out[202]: [0, 99, 199, 299, 399] 

標籤:

In [203]: lkp.Val.tolist() 
Out[203]: ['AAA', 'BBB', 'CCC', 'DDD'] 

注意: lkp必須先用['Min', 'Max']排序後再用於binslabels

這裏是一個小的演示進行排序:

In [2]: lkp 
Out[2]: 
    Min Max Val 
0 300 399 DDD 
1 100 199 BBB 
2 1 99 AAA 
3 200 299 CCC 

In [4]: lkp = lkp.sort_values(['Min','Max']) 

In [5]: lkp 
Out[5]: 
    Min Max Val 
2 1 99 AAA 
1 100 199 BBB 
3 200 299 CCC 
0 300 399 DDD 
+0

非常感謝您的答覆!那麼我會只是'as.type(str)'到上面創建的'Val'列來減少內存負載? – user791411

+1

@ user791411,歡迎您!不,你想保留它作爲'category' - 它只是一個「調整過的」字符串dtype。我已經添加了'str_col'以顯示內存使用的差異 – MaxU

+0

好的謝謝! **問題**:我收到一條錯誤消息,說「」ValueError:垃圾箱必須單調遞增。「'我應該如何更改代碼? – user791411