2012-07-13 86 views
2

DataFrame我要覆蓋與另一列的一個切片。熊貓的熊貓(v0.8.0)的高級索引分配

在下面的代碼拋出列出的錯誤。

什麼將是實現這一目標的有效替代的方法?

df = DataFrame({'a' : range(0,7), 
'b' : np.random.randn(7), 
'c' : np.random.randn(7), 
'd' : np.random.randn(7), 
'e' : np.random.randn(7), 
'f' : np.random.randn(7), 
'g' : np.random.randn(7)}) 

# overwrite cols 
df.ix[:,'b':'d'] = df.ix[:, 'e':'g'] 

Traceback (most recent call last): 
File "C:\Python27\lib\site-packages\pandas\core\indexing.py", line 68, in __setitem__ 
self._setitem_with_indexer(indexer, value) 
File "C:\Python27\lib\site-packages\pandas\core\indexing.py", line 98, in _setitem_with_indexer 
raise ValueError('Setting mixed-type DataFrames with ' 
ValueError: Setting mixed-type DataFrames with array/DataFrame pieces not yet supported 

編輯

而作爲置換的,我怎麼可能還指定行的子集來設置

df.ix[df['a'] < 3, 'b':'d'] = df.ix[df['a'] < 3, 'e':'g'] 

回答

6

的問題是,使用.ix[]返回一個視圖到DataFrame的該子集的實際內存對象,而不是由其內容構成的新DataFrame。

而是使用

# The left-hand-side does not use .ix, since we're assigning into it. 
df[['b','c']] = df.ix[:,'e':'f'].copy() 

請注意,您將需要.copy()如果你在使用.ix做切片意圖,否則會使一組列「B」和「C」作爲在內存中的同一對象爲列「E」和「F」,這似乎並不像你想在這裏做什麼。

另外,爲了避免擔心複製,你可以這樣做:

df[['b','c']] = df[['e','f']] 

如果索引事項您的方便,來模擬這種效果的一種方法是寫自己的功能:

def col_range(df, col1, col2): 
    return list(dfrm.ix[dfrm.index.values[0],col1:col2].index) 

現在你可以做到以下幾點:

df[col_range(df,'b','d')] = df.ix[:,'e':'g'].copy() 

注:在日的col_rangeË定義我用其將選擇的數據幀的第一行的第一個索引。我這樣做是因爲使整個數據幀的視圖只是選擇部分列似乎浪費了,而一個行可能不會沒關係。由於以這種方式進行切片會生成一個Series,所以提取列的方法實際上是獲取索引,然後將它們作爲列表返回。

添加了對其他排片要求:

要指定分配一組行,你可以使用.ix,但你需要指定只是一個在右邊值的矩陣。在右側具有子DataFrame的結構會導致問題。

df.ix[0:4,col_range(df,'b','d')] = df.ix[0:4,'e':'g'].values 

,可隨時更換[0:4][df.index.values[i]:df.index.values[j]][df.index.values[i] for i in range(N)]或或甚至與諸如[df['a']>5]邏輯值,其中的「a」的列超過5時,例如只得到的行。

邏輯索引的例子的全切片要將列「A」大於5列「E」小於10可能是這樣的:

import numpy as np 
my_rows = np.logical_and(df['a'] > 5), df['e'] < 10) 
df.ix[my_rows,col_range(df,'b','d')] = df.ix[my_rows,'e':'g'].values 

在很多情況下,你不會需要在左側使用.ix(我建議不要這樣做,因爲它只適用於某些情況,而不適用於其他情況)。舉例來說,像這樣:

df["A"] = np.repeat(False, len(df)) 
df["A"][df["B"] > 0] = True 

將工作就是,需要查明條件爲真行無特殊.ix。當右邊的東西很複雜時,似乎需要左邊的.ix

+0

col_range函數是一個好主意,因爲我仍然要在列中指定切片。作爲一個置換,我怎麼能指定分配中的行的子集(上面編輯的問題)。 – brendan 2012-07-17 09:24:29

+0

用行切片的額外信息更新了答案。 – ely 2012-07-17 12:25:09

+0

感謝您的更新 - 儘管當我嘗試df.ix [my_rows,col_range(df,'b','d')] = df.ix [my_rows,'e':'g'] .value時,會引發ValueError也。 – brendan 2012-07-18 09:53:43