2017-04-02 63 views
0

我正在玩泰坦尼克號數據集,我想要做的是填寫Age列的所有NaN/Null值,其中值基於Pclass基於條件切片更改熊貓數據框中的單元格

下面是一些數據:

train 

PassengerId Pclass Age 
0 1 3 22 
1 2 1 35 
2 3 3 26 
3 4 1 35 
4 5 3 35 
5 6 1 NaN 
6 7 1 54 
7 8 3 2 
8 9 3 27 
9 10 2 14 
10 11 1 Nan 

這裏是我想和落得什麼:

PassengerId Pclass Age 
0 1 3 22 
1 2 1 35 
2 3 3 26 
3 4 1 35 
4 5 3 35 
5 6 1 35 
6 7 1 54 
7 8 3 2 
8 9 3 27 
9 10 2 14 
10 11 1 35 

我想出的第一件事情是這樣的 - 在簡潔的利益,我Pclass只包括一個等於1而不包括2和3的切片:

Pclass_1 = train['Pclass']==1 

train[Pclass_1]['Age'].fillna(train[train['Pclass']==1]['Age'].median(), inplace=True) 

據我所知,這種方法創建一個視圖,而不是編輯train本身(我不太明白這與副本有什麼不同,或者如果他們在記憶方面是類似的 - 那是我會喜歡的聽到如果可能)。我特別喜歡關於主題View vs Copy, How Do I Tell?的Q/A,但它不包括我正在尋找的洞察力。

翻閱熊貓文檔,我瞭解了爲什麼你想用.loc來避免這個陷阱。然而,我似乎無法得到正確的語法。

Pclass_1 = train.loc[:,['Pclass']==1] 

Pclass_1.Age.fillna(train[train['Pclass']==1]['Age'].median(),inplace=True) 

我迷失在指數中。這最終會尋找一個名爲False的列,這個列顯然不存在。如果沒有鏈接索引,我不知道如何做到這一點。 train.loc[:,train['Pclass']==1]返回異常IndexingError: Unalignable boolean Series key provided

+1

通常,如果您提供[最小,完整和可驗證]示例(特別是可切割和粘貼的示例),這些問題將得到更快速和更大的回答示例和預期數據。 –

+0

我現在已經添加了一些來自真實數據框的示例數據。 – prdctofchem

+0

@prdctofchem我已根據添加的示例數據更新了我的答案。 – Craig

回答

0

在線路的這一部分,

train.loc[:,['Pclass']==1] 

部分['Pclass'] == 1被列表['Pclass']比較值1,它返回False。然後.loc[]被評估爲導致錯誤的.loc[:,False]

我想你的意思:

train.loc[train['Pclass']==1] 

將選擇所有行的其中Pclass是1.本修正錯誤,但它仍然給你「SettingWithCopyWarning」。

EDIT 1

(舊代碼移除)

下面是一個使用groupbytransform創建包含中值Age每個Pclass一個Series 的方法。然後使用Series作爲fillna()的參數以用中位數代替缺失值。使用這種方法將同時修正所有乘客類別,這是OP最初要求的。該解決方案來自答案Python-pandas Replace NA with the median or mean of a group in dataframe

import pandas as pd 
from io import StringIO 

tbl = """PassengerId Pclass Age 
0 1 3 22 
1 2 1 35 
2 3 3 26 
3 4 1 35 
4 5 3 35 
5 6 1 
6 7 1 54 
7 8 3 2 
8 9 3 27 
9 10 2 14 
10 11 1 
""" 

train = pd.read_table(StringIO(tbl), sep='\s+') 
print('Original:\n', train) 
median_age = train.groupby('Pclass')['Age'].transform('median') #median Ages for all groups 
train['Age'].fillna(median_age, inplace=True) 
print('\nNaNs replaced with median:\n', train) 

的代碼產生:

Original: 
    PassengerId Pclass Age 
0    1  3 22.0 
1    2  1 35.0 
2    3  3 26.0 
3    4  1 35.0 
4    5  3 35.0 
5    6  1 NaN 
6    7  1 54.0 
7    8  3 2.0 
8    9  3 27.0 
9   10  2 14.0 
10   11  1 NaN 

NaNs replaced with median: 
    PassengerId Pclass Age 
0    1  3 22.0 
1    2  1 35.0 
2    3  3 26.0 
3    4  1 35.0 
4    5  3 35.0 
5    6  1 35.0 
6    7  1 54.0 
7    8  3 2.0 
8    9  3 27.0 
9   10  2 14.0 
10   11  1 35.0 

有一點需要注意的是,這條線,它採用inplace=True

train['Age'].fillna(median_age, inplace=True) 

可以替換分配使用.loc

train.loc[:,'Age'] = train['Age'].fillna(median_age) 
+0

如果我將它應用於多個Pclass中具有NaN值的數據集,是否將它填充到正確的位置,因爲我有一個GroupBy df?或者在我這樣做之前還需要指定匹配Pclass值?我也在想,如果簡單地使用聚合方法'.median()'而不是'.transform('median')'是我的更好的選擇。 – prdctofchem

+0

@prdctofchem對於超過1個Pclass中的NaN,'groupby'可以正常工作。我只是做了一個測試,並且'transform()'_is required_爲了這個工作。您應該通過兩種方式來測試代碼,以瞭解爲什麼'transform()'很重要。如果您發現此答案有幫助,請通過點擊灰色複選標記將其解決並接受答案。 – Craig

+0

有關'transform()'的更多信息:[瞭解熊貓中的變換函數](http://pbpython.com/pandas_transform.html) – prdctofchem

相關問題