提问者:小点点

将λ函数应用于列在熊猫中失败了


我不知道为什么索引方法在执行按列应用函数时有不一致的行为。

数据帧为:

df = pd.DataFrame( [(1, 'Hello'), (2, "World")])
df.columns=['A', 'B']

我想把lambda应用到第二列,是不是说Series对象不能应用?

print df.iloc[:, 1:2].apply(lambda x: x.upper()).head()
 **AttributeError**:("'Series' object has no attribute 'upper'", u'occurred at index B')
print df.loc[:, ['B']].apply(lambda x: x.upper()).head()
 **AttributeError**:("'Series' object has no attribute 'upper'", u'occurred at index B')

而是下面的索引方法工作得很好。

print df.loc[:, 'B'].apply(lambda x: x.upper()).head()

为什么啊?我认为三种指数方法是等价的?以上三种索引方法几乎都有相同的结果,如果打印出来,即:

   B
0  Hello
1  World

并打印df。loc[:,'B']获取

0  Hello
1  World
Name: B, dtype: object

这些差异意味着什么?


共2个答案

匿名用户

当你用'B'索引时,你会得到一个系列。当您使用1:2['B']进行索引时,您会得到一个只有一列的DataFrame。当您对一个系列使用应用时,您的函数将在每个元素上被调用。当您在DataFrame上使用应用时,您的函数将在每一列上被调用。

所以不,它们是不等价的。当你有一个系列,你可以使用你想要的功能。当您有一列数据帧时,您不能这样做,因为它将该列作为其参数传递,并且该列是一个没有upper方法的序列。

你可以看到它们不一样,因为打印出来的结果不同。是的,它们几乎一样,但不一样。第一个有一个列标题,表示它是一个数据帧;第二个没有列标题,但底部有“Name”,表示它是一个系列。

匿名用户

正如@BrenBarn所提到的,不同之处在于,在df.iloc[:,1:2]的情况下,DataFrame只有一列,而在df.loc[:,'B']的情况下,您有一个系列...只是一个小补充,转换DataFrame与一列成系列,你可以使用pandas.squeeze()方法:

>>> df.iloc[:, 1:2]
       B
0  Hello
1  World
>>> df.iloc[:, 1:2].squeeze()
0    Hello
1    World
Name: B, dtype: object

然后,您可以使用应用(您不必使用lambda,BTW):

>>> df.iloc[:, 1:2].squeeze().apply(str.upper)
0    HELLO
1    WORLD
Name: B, dtype: object

如果要对数据帧应用upper,可以使用pandas。applymap():

>>> df.iloc[:, 1:2].applymap(str.upper)
       B
0  HELLO
1  WORLD