在Python中使用ix子集化DataFrame

时间:2015-02-17 16:56:48

标签: python pandas dataframe subset

我正在尝试了解子集在pandas DataFrame中的工作原理。我做了一个随机数据框如下。

import pandas as pd
import numpy as np

np.random.seed(1234)
X = pd.DataFrame({'var1' : np.random.randint(1,6,5), 'var2' : np.random.randint(6,11,5), 
                  'var3': np.random.randint(11,16,5)})
X = X.reindex(np.random.permutation(X.index))
X.iloc[[0,2], 1] = None

X返回,

   var1  var2  var3
0     3   NaN    11
4     3     9    13
3     2   NaN    14
2     5     9    12
1     2     7    13

pandas方法.loc严格基于标签,.iloc用于整数位置。 .ix可用于组合基于位置的索引和标签。

但是,在上面的例子中,行索引是整数,.ix将它们理解为行索引而不是位置。假设我要检索' var2'的前两行。在R中,X[1:2, 'var2']会给出答案。在Python中,X.ix[[0,1], 'var2']返回NaN 7而不是NaN 9

问题是"是否有一种简单的方法让.ix知道指数是基于位置的?"

我已经为此找到了一些解决方案,但在某些情况下它们并不简单直观。

例如,通过使用下面的_slice(),我可以得到我想要的结果。

>>> X._slice(slice(0, 2), 0)._slice(slice(1,2),1)
   var2
0   NaN
4     9

当行索引不是整数时,没有问题。

>>> X.index = list('ABCED')
>>> X.ix[[0,1], 'var2']
A   NaN
B     9
Name: var2, dtype: float64

1 个答案:

答案 0 :(得分:1)

您可以使用X['var2'].iloc[[0,1]]

In [280]: X['var2'].iloc[[0,1]]
Out[280]: 
0   NaN
4     9
Name: var2, dtype: float64

由于X['var2']X视图X['var2'].iloc[[0,1]]对两者都是安全的 访问和分配。但是如果你使用这个"链式索引" 模式(例如,此处使用的逐列 - 然后 - 索引 - { - 1}}模式)用于分配,因为它不 概括为具有多列的分配的情况。

例如,iloc会生成一个副本 X的子DataFrame因此分配给此子DataFrame不会修改X[['var2', 'var3']].iloc[[0,1]] = ...。 有关详细说明,请参阅"Why assignments using chained indexing fails"上的文档。

具体并说明为什么这种视图与副本的区别很重要:如果你打开了这个警告:

X

然后此分配会引发pd.options.mode.chained_assignment = 'warn' 警告:

SettingWithCopyWarning

并且分配无法修改In [252]: X[['var2', 'var3']].iloc[[0,1]] = 100 SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy self._setitem_with_indexer(indexer, value) 。 EEK!

X

要解决此问题,当您希望作业影响In [281]: X Out[281]: var1 var2 var3 0 3 NaN 11 4 3 9 13 3 2 NaN 14 2 5 9 12 1 2 7 13 时,您必须这样做 分配给单个索引器(例如XX.iloc = ...X.loc = ...) - 即没有链式索引

在这种情况下,您可以使用

X.ix = ...

但我想知道是否有更好的方法,因为这不是非常漂亮。