2014-03-05 58 views
5

我有一個大小適中的(約60,000行15列)csv文件,我正在使用熊貓。每一行代表一個人幷包含個人數據。我想要匿名呈現數據。我希望這樣做的一種方式是通過替換特定列中的值來避免它們很少出現。我最初試圖這樣做如下:取代熊貓數據框中罕見的值

def clean_data(entry): 
    if df[df.column_name == entry].index.size < 10: 
     return 'RARE_VALUE' 
    else: 
     return entry 

df.new_column_name = df.column_name.apply(clean_data) 

但運行它凍結我的系統每一次。這不幸意味着我沒有有用的調試數據。有誰知道這樣做的正確方法?該列包含字符串和空值。

+0

你可以[設置應用進度表](http://stackoverflow.com/a/18611535/1240268),但這顯然會減慢你正在做的任何事情。一般來說,在一個應用程序中返回不同類型的數據(這裏是一個字符串或一個系列)是一個糟糕的主意,目前還不清楚你想要應用程序返回什麼...... –

+0

@AndyHayden你的評論暗示我可能不瞭解'apply'正常。我的理解是,如果條件滿足,我的函數將返回字符串'RARE_VALUE',但如果不存在則保留現有字符串/ null。這是不正確的? –

+0

啊,等一下,我看到你在說什麼,我誤以爲這是一個DataFrame適用。不,你是對的,但在每一步布爾掩模是**慢**! –

回答

7

我想你想的GroupBy列名:

g = df.groupby('column_name') 

您可以使用過濾器,例如,僅返回誰在列名的東西出現了10倍以上的那些行:

g.filter(lambda x: len(x) >= 10) 

爲了與「RARE_VALUE」可以使用變換覆蓋柱(其計算一次結果對於每個組,並適當地圍繞擴散它):

df.loc[g[col].transform(lambda x: len(x) < 10).astype(bool), col] = 'RARE_VALUE' 

由於DSM指出,下面的技巧是更快:

df.loc[df[col].value_counts()[df[col]].values < 10, col] = "RARE_VALUE" 

這裏的一些timeit信息(顯示DSM的解決方案多麼令人印象深刻!):

In [21]: g = pd.DataFrame(np.random.randint(1, 100, (1000, 2))).groupby(0) 

In [22]: %timeit g.filter(lambda x: len(x) >= 10) 
10 loops, best of 3: 67.2 ms per loop 

In [23]: %timeit df.loc[g[1].transform(lambda x: len(x) < 10).values.astype(bool), 1] 
10 loops, best of 3: 44.6 ms per loop 

In [24]: %timeit df.loc[df[1].value_counts()[df[1]].values < 10, 1] 
1000 loops, best of 3: 1.57 ms per loop 
+4

'df.loc [df [col] .value_counts()[df [col]]。values <10,col] =「RARE_VALUE」'可能會快一點。 – DSM

+0

@DSM這是一些適當的巫術魔術...... *當然*這不是更快! –

+0

關心一些quatloos? – DSM