在 Python 中使用 ix 对 DataFrame 进行子集化
Subsetting DataFrame using ix in Python
我正在尝试了解子集在 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 returns,
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']
returns NaN 7
而不是 NaN 9
.
问题是"Is there a simple way to let .ix
know the indices are position based?"
我已经找到了一些解决方案,但在某些情况下它们并不简单直观。
例如,通过如下使用_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
您可以使用 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]]
对两者都是安全的
访问和分配。但是如果你使用这个"chained indexing"要小心
模式(例如这里使用的 index-by-column-then-index-by-iloc
模式)用于赋值,因为它不
概括为多列赋值的情况。
例如,X[['var2', 'var3']].iloc[[0,1]] = ...
生成一个 copy
X 的子 DataFrame,因此分配给此子 DataFrame 不会修改 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)
并且赋值修改失败 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
要解决此问题,当您希望分配影响 X
时,您必须
分配给单个索引器(例如X.iloc = ...
或X.loc = ...
或X.ix = ...
)——也就是说,没有链式索引.
在这种情况下,您可以使用
In [265]: X.iloc[[0,1], X.columns.get_indexer_for(['var2', 'var3'])] = 100
In [266]: X
Out[266]:
var1 var2 var3
0 3 100 100
4 3 100 100
3 2 NaN 14
2 5 9 12
1 2 7 13
但我想知道是否有更好的方法,因为这不是很漂亮。
我正在尝试了解子集在 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 returns,
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']
returns NaN 7
而不是 NaN 9
.
问题是"Is there a simple way to let .ix
know the indices are position based?"
我已经找到了一些解决方案,但在某些情况下它们并不简单直观。
例如,通过如下使用_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
您可以使用 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]]
对两者都是安全的
访问和分配。但是如果你使用这个"chained indexing"要小心
模式(例如这里使用的 index-by-column-then-index-by-iloc
模式)用于赋值,因为它不
概括为多列赋值的情况。
例如,X[['var2', 'var3']].iloc[[0,1]] = ...
生成一个 copy
X 的子 DataFrame,因此分配给此子 DataFrame 不会修改 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)
并且赋值修改失败 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
要解决此问题,当您希望分配影响 X
时,您必须
分配给单个索引器(例如X.iloc = ...
或X.loc = ...
或X.ix = ...
)——也就是说,没有链式索引.
在这种情况下,您可以使用
In [265]: X.iloc[[0,1], X.columns.get_indexer_for(['var2', 'var3'])] = 100
In [266]: X
Out[266]:
var1 var2 var3
0 3 100 100
4 3 100 100
3 2 NaN 14
2 5 9 12
1 2 7 13
但我想知道是否有更好的方法,因为这不是很漂亮。