2012-07-13 173 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