在 Pandas 的 apply 函数中获取一行的索引

243

我正在尝试在 Pandas 中应用于整个 DataFrame 的函数中访问行的索引。我的代码类似于:

df = pandas.DataFrame([[1,2,3],[4,5,6]], columns=['a','b','c'])
>>> df
   a  b  c
0  1  2  3
1  4  5  6

我将定义一个函数,用于访问给定行的元素

def rowFunc(row):
    return row['a'] + row['b'] * row['c']

我可以这样使用它:

df['d'] = df.apply(rowFunc, axis=1)
>>> df
   a  b  c   d
0  1  2  3   7
1  4  5  6  34

太棒了!那么如果我想在函数中加入索引应该怎么做呢? 在添加d之前,此DataFrame中任何给定行的索引将为Index([u'a', u'b', u'c', u'd'], dtype='object'),但我只想要0和1。 所以我不能直接访问row.index

我知道我可以在表格中创建一个临时列来存储索引,但我想知道它是否存储在行对象中的某个位置。


1
顺便问一下:你需要使用apply的原因是什么?它比在框架本身上执行向量化操作要慢得多。(有时,应用程序确实是完成某些操作最简单的方法,并且性能考虑经常被夸大,但对于您特定的示例,不使用它同样容易。) - DSM
6
实际上,我每一行都使用不同的行元素调用另一个对象的构造函数。我只是想提供一个简单的示例来说明问题。 - Mike
3个回答

286

要访问此情况下的索引,您需要访问name属性:

In [182]:

df = pd.DataFrame([[1,2,3],[4,5,6]], columns=['a','b','c'])
def rowFunc(row):
    return row['a'] + row['b'] * row['c']

def rowIndex(row):
    return row.name
df['d'] = df.apply(rowFunc, axis=1)
df['rowIndex'] = df.apply(rowIndex, axis=1)
df
Out[182]:
   a  b  c   d  rowIndex
0  1  2  3   7         0
1  4  5  6  34         1

请注意,如果这确实是您想要做的事情,那么以下方法可以实现,而且速度更快:

In [198]:

df['d'] = df['a'] + df['b'] * df['c']
df
Out[198]:
   a  b  c   d
0  1  2  3   7
1  4  5  6  34

In [199]:

%timeit df['a'] + df['b'] * df['c']
%timeit df.apply(rowIndex, axis=1)
10000 loops, best of 3: 163 µs per loop
1000 loops, best of 3: 286 µs per loop

编辑

看到这个问题已经超过3年了,你可以这样做:

In[15]:
df['d'],df['rowIndex'] = df['a'] + df['b'] * df['c'], df.index
df

Out[15]: 
   a  b  c   d  rowIndex
0  1  2  3   7         0
1  4  5  6  34         1

但是假设它不像这样微不足道,无论你的rowFunc到底在做什么,你都应该尝试使用向量化函数,并将它们用于df索引:

In[16]:
df['newCol'] = df['a'] + df['b'] + df['c'] + df.index
df

Out[16]: 
   a  b  c   d  rowIndex  newCol
0  1  2  3   7         0       6
1  4  5  6  34         1      16

7
如果有一个Multindex的情况下,如果name是一个命名元组,则会很方便,这样就可以通过名称查询特定的索引级别。 - Konstantin

62

要么:

1. 在 apply(..., axis=1) 调用中使用 row.name:

df = pandas.DataFrame([[1,2,3],[4,5,6]], columns=['a','b','c'], index=['x','y'])

   a  b  c
x  1  2  3
y  4  5  6

df.apply(lambda row: row.name, axis=1)

x    x
y    y

2. 使用 iterrows()(速度较慢)

DataFrame.iterrows() 允许您迭代行并访问它们的索引:

for idx, row in df.iterrows():
    ...

3
如果有相关的担忧,通常使用'itertuples'会表现得更好:https://dev59.com/cmAf5IYBdhLWcg3wOQq2 - dpb

14
回答原问题:是的,您可以在 apply() 中访问行的索引值。 它在键name下可用,并且需要指定axis = 1(因为lambda处理行的列而不是列的行)。
工作示例(pandas 0.23.4):
>>> import pandas as pd
>>> df = pd.DataFrame([[1,2,3],[4,5,6]], columns=['a','b','c'])
>>> df.set_index('a', inplace=True)
>>> df
   b  c
a      
1  2  3
4  5  6
>>> df['index_x10'] = df.apply(lambda row: 10*row.name, axis=1)
>>> df
   b  c  index_x10
a                 
1  2  3         10
4  5  6         40

4
适用于具有多层索引的数据框:行名称变为元组。 - Charles Fox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接