2017-01-19 47 views
1

我已經將Excel工作表導入Pandas的數據框中。空白值被'NA'取代。我想要做的是,對於每個行值,將其替換爲基於字典或數據框的索引。使用Pandas/Python更新可變大小的數據框

df1 = pd.DataFrame(
    {'c1':['a','a','b','b'], 'c2':['1','2','1','3'], 'c3':['2','NA','3','NA']},index=['first','second','third','last']) 

>>> df1 
     c1 c2 c3 
first a 1 2 
second a 2 NA 
third b 1 3 
last b 3 NA 

我想根據另一個數據幀(或字典)的指數替換每一行中的值。

df2=pd.DataFrame(
    {'val':['v1','v2','v3']},index=['1','2','3']) 

>>> df2 
    val 
1 v1 
2 v2 
3 v3 

使得輸出變爲

>>> out 
     c1 c2 c3 
first a v1 v2 
second a v2 NA 
third b v1 v3 
last b v3 NA 

你將如何通過熊貓和/或Python這樣做呢?一種方法是逐行搜索,但也許有一種更簡單的方法?

編輯:重要的是,由於我正在處理尺寸爲4653行×1984列的'df1',因此性能在我的實際情況中成爲問題。

預先感謝您

+0

我認爲要訪問每個單元格,並做一個檢查,你必須'iterrows'這不是硬的大聲笑。 – Bobby

+0

@Bobby謝謝你的評論。請隨時張貼它作爲一個新的答案 – Sosi

+0

人看看這些奇特的答案。我只是沒有信心。學習太大聲了 – Bobby

回答

1

原來的答覆

s = df1.squeeze() 
df2.replace(s) 

replace非常非常慢。對於像您這樣的大型數據集,請檢查以下示例,該示例在大約20秒內完成了超過3000萬個值(超過您的1000萬個值)。查找系列包含從0到100萬的900k值。

'地圖'要快得多。 map唯一的問題是它會替換未找到的值,因此您必須使用fillna和原始DataFrame來替換那些缺失的值。

n = 10000000 
df = pd.DataFrame({'c1':np.random.choice(list('abcdefghijkl'), n), 
       'c2':np.random.randint(0, 1000000, n), 
       'c3':np.random.randint(0, 1000000, n)}) 

s = pd.Series(index=np.random.choice(np.arange(1000000), 900000, replace=False), 
       data=np.random.choice(list('adsfjhqwoeriouzxvmn'), 900000, replace=True)) 

df.stack().map(s).unstack().fillna(df) 

你也可以做到這一點這是運行在我的數據的速度更快,但你的數據是非常廣泛的,所以可能會比較慢

df.apply(lambda x: x.map(s)).fillna(df) 

而就類似你一個數據幀,我越來越6S到完成。

df = pd.DataFrame(np.random.randint(0, 1000000, (5000, 2000))) 
df.stack().map(s).unstack().fillna(df) 
+0

謝謝你的回答。您的建議完美適用於小型測試案例。例如,對我的真實數據使用5x4'df1'是完美的,但對於整個數據幀來說,它需要很長時間並凍結我的電腦(可能是因爲它正在處理所有行/列,包括哪裏有'NA'?)。任何方式來改善這一點? – Sosi

+0

檢查'np。哪裏會爲你工作。所有的值都是字符串嗎? –

+0

所有的搜索值都是整數(類似於上面的工作示例)。我會檢查它,但我需要提出一個總體規則,因爲這些整數(作爲鍵/索引)從1到100000,但並非所有整數都在那裏。 – Sosi

4

一種方法是stack + replace + unstack組合:

df1.stack().replace(df2.val).unstack() 

enter image description here

+1

看起來你不必堆疊。 df1.replace(df2.val)的作品。 –

+0

哦,是的。我一直認爲你不能像'map'那樣直接在'DF'對象上直接使用'replace'。我會讓我的答案保持不變,因爲它會重複你的答案。 –