2014-08-28 32 views
1

我是新來的python和熊貓,我不明白爲什麼有時我可以複製或操縱數據框列,有時我不能。這裏被稱爲數據幀DF:熊貓數據框條目有時可以修改,有時不是

  A  B   C 
0 hello hola bonjour 
1 goodbye adios au revoir 

我的第一個修改將由一行覆蓋列「C」行中的for循環(是的,有可能是更好的方式來做到這一點 - 這不是重點)其結果是如我所料:

for index,row in df.iterrows(): 
    row['C'] = row['A'] 

     A  B  C 
0 hello hola hello 
1 goodbye adios goodbye 

我可以使用下面的for循環,並再次,我得到了我的預期增加一個新的列:

for index,row in df.iterrows(): 
    df.ix[index,'D'] = len(row['C']) 

     A  B  C D 
0 hello hola hello 5 
1 goodbye adios goodbye 7 

現在我嘗試幾乎完全與我第一次修改相同的東西(使用for-loop逐行覆蓋列'B'),但這次它不起作用。數據幀這次不會改變。

for index,row in df.iterrows(): 
    row['B'] = row['A'] 

     A  B  C D 
0 hello hola hello 5 
1 goodbye adios goodbye 7 

我想知道兩件事情:

1)爲什麼相同的代碼覆蓋列有時,但不是其他時間?

2)我做錯了什麼事情導致熊貓以這種不直觀的方式行事?如果是這樣,那麼從另一列構建一列的正確方法是什麼,以避免這種事情發生?

任何好的答案或建議是非常感謝。謝謝!

回答

2

首先,你應該從來沒有嘗試修改你的數據幀,同時迭代它。

爲了構建一個新的列,則可以只是:

df['C'] = df['A'] 

或專門爲獲取每個字符串的長度(見docs):

df['D'] = df['C'].str.len() 

的原因不同的輸出是它可以根據具體情況獲得原始數據的視圖或副本(如果它在dtypes中是同質的)。
就你而言,第一次,所有列都是字符串類型,你會看到原始數據,並且修改將反映在原始數據框中。但是在添加欄D後,列具有不同的dtype,並且在迭代時會得到一個副本。出於這個原因,適應性不會反映在您最後一種情況下的原始數據框中(另請參閱此issue)。

2

代碼生成不同答案的原因與itterrows有關,它提供了數據的視圖與副本。如果您分配給視圖,它會修改原始數據,而分配給副本則什麼也不做。

從我的理解(見本answer),itterrows只產生一個單dtyped的對象,這是當所有列都是字符串分配工作,但一旦你添加一個整數列失敗的視圖。

關於如何根據其他列創建新列 - 如果您絕對需要迭代,則可以使用loc進行分配,如同在一個示例中所做的那樣。但是你應該總是尋找一個矢量化的解決方案,然後看看apply,然後才考慮迭代。有關更多背景,請參閱此answer