索引 Pandas 个数据框:整数行,命名列

Indexing Pandas data frames: integer rows, named columns

df 是一个 pandas 数据框。

引用行时,df.ix[row_idx, ] 只想给出名称。例如

df = pd.DataFrame({'a' : ['one', 'two', 'three','four', 'five', 'six'],
                   '1' : np.arange(6)})
df = df.ix[2:6]
print(df)

   1      a
2  2  three
3  3   four
4  4   five
5  5    six

df.ix[0, 'a']

抛出一个错误,它没有给出 return 'two'。

引用列时,iloc 更喜欢整数,而不是名称。例如

df.ix[2, 1]

returns 'three',不是 2。(尽管 df.idx[2, '1'] 确实 return 2)。

奇怪的是,我想要完全相反的功能。通常我的列名很有意义,所以在我的代码中我直接引用它们。但是由于大量观察清理,我的 pandas 数据框中的行名称通常不对应 range(len(df))

我意识到我可以使用:

df.iloc[0].loc['a'] # returns three

不过好像很难看!有谁知道更好的方法来做到这一点,以便代码看起来像这样?

df.foo[0, 'a'] # returns three

事实上,是否可以将我自己的新方法添加到 pandas.core.frame.DataFrames,例如 df.idx(rows, cols) 实际上是 df.iloc[rows].loc[cols]?

这是一个迟到的答案,但@unutbu 的评论仍然有效,并且是解决此问题的好方法。

使用整数行和命名列(标记列)索引 DataFrame:

df.loc[df.index[#], 'NAME'] 其中 # 是有效的整数索引,NAME 是列的名称。

我们可以重置索引,然后像这样使用基于 0 的索引

df.reset_index(drop=True).loc[0,'a']

编辑:从列名称索引 'a' 中删除了 [],因此它只输出值

像 df["a"][0] 这样的东西对我来说工作正常。你可以试试看!

要在 DataFrame by row/column 标签中获取或设置 单个 值,您最好按原样使用 DataFrame.at instead of DataFrame.loc。 ..

  1. 更快
  2. 您更明确地表示只想访问一个值。

其他人已经表明,如果您从行的整数位置开始,您仍然必须首先使用 DataFrame.index 找到行标签,因为 DataFrame.at 只接受标签:

df.at[df.index[0], 'a']
# Out: 'three'

基准:

%timeit df.at[df.index[0], 'a']
# 7.57 µs ± 30.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit df.loc[df.index[0], 'a']
# 10.9 µs ± 53.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit df.iloc[0, df.columns.get_loc("a")]
# 13.3 µs ± 24 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

完整性:

DataFrame.iat 用于按整数位置访问 row/column 对的单个值。

现有的答案对我来说似乎是短视的。

有问题的解决方案

  1. df.loc[df.index[0], 'a']
    这里的策略是获取第0行的行标签,然后照常使用.loc。我看到两个问题。

    1. 如果 df 有重复的行标签,df.loc[df.index[0], 'a'] 可以 return 多行。
    2. .loc.iloc 慢,所以你在这里牺牲了速度。
  2. df.reset_index(drop=True).loc[0, 'a']
    这里的策略是重置索引,使行标签变为 0、1、2,...因此 .loc[0] 给出与 .iloc[0] 相同的结果。尽管如此,这里的问题仍然是运行时,因为 .loc.iloc 慢,并且您会产生重置索引的成本。

更好的解决方案

我建议关注 :

df.iloc[0, df.columns.get_loc("a")]

本质上,这与 df.iloc[0, 0] 相同,只是我们使用 df.columns.get_loc("a").

动态获取列索引

要索引多个列,例如 ['a', 'b', 'c'],请使用:

df.iloc[0, [df.columns.get_loc(c) for c in ['a', 'b', 'c']]]

更新

这是讨论 here as part of my course on Pandas

一个很晚的答案,但令我惊讶的是 pandas 这么多年了仍然没有这样的功能。如果它让你很烦,你可以将自定义索引器猴子修补到 DataFrame 中:

class XLocIndexer:
    def __init__(self, frame):
        self.frame = frame
    
    def __getitem__(self, key):
        row, col = key
        return self.frame.iloc[row][col]

pd.core.indexing.IndexingMixin.xloc = property(lambda frame: XLocIndexer(frame))

# Usage
df.xloc[0, 'a'] # one