【问题标题】:Subsetting DataFrame using ix in Python在 Python 中使用 ix 子集 DataFrame
【发布时间】:2015-02-17 16:56:47
【问题描述】:

我正在尝试了解子集在 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

【问题讨论】:

  • 但是你有一个使用整数位置索引的方法,那么为什么不直接使用iloc 来避免不明确的索引呢?
  • @EdChum 是的,X.iloc[[0,1],1] 返回子集,但有一种情况是您只知道属性名称 'var2'。
  • @EdChum 也许你是对的。我想不出我只知道属性名称的任何情况。我想我走得太远了。
  • 你可以使用X['var2'].iloc[[0,1]]
  • @NeoJi: X['var2'].iloc[[0,1]] 对访问和分配都是安全的,但如果将其用于分配,请小心,因为它不能推广到具有多列分配的情况。例如,X[['var2', 'var3']].iloc[[0,1]] = ... 生成X 的子DataFrame 的副本,因此分配给该子DataFrame 不会修改X。请参阅"Why assignments using chained indexing fails" 上的文档。

标签: python pandas dataframe subset


【解决方案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]] 对双方都是安全的 访问和分配。但是如果你使用这个“链式索引”要小心 分配模式(例如这里使用的 index-by-column-then-index-by-iloc 模式),因为它不 推广到多列赋值的情况。

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

具体并说明为什么这种查看与复制的区别很重要:如果您打开了此警告:

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

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

【讨论】:

    猜你喜欢
    • 2013-10-14
    • 2018-04-01
    • 2012-08-16
    • 2020-05-16
    • 2013-11-09
    • 1970-01-01
    • 2018-07-21
    • 2019-12-05
    相关资源
    最近更新 更多