Python 熊猫:使用loc在数据帧索引上迭代

Python 熊猫:使用loc在数据帧索引上迭代,python,pandas,indexing,Python,Pandas,Indexing,我似乎找不到.loc行为背后的原因。我知道它是基于标签的,所以如果我迭代索引对象,下面的最小示例应该可以工作。但事实并非如此。我当然在谷歌上搜索过,但我需要一个已经掌握了索引的人的额外解释 导入日期时间 作为pd进口熊猫 dict_weekday={1:'MON',2:'TUE',3:'WED',4:'THU',5:'FRI',6:'SAT',7:'SUN'} df=pd.DataFrame(pd.date_范围(datetime.date(2014,1,1),datetime.date(201

我似乎找不到.loc行为背后的原因。我知道它是基于标签的,所以如果我迭代索引对象,下面的最小示例应该可以工作。但事实并非如此。我当然在谷歌上搜索过,但我需要一个已经掌握了索引的人的额外解释

导入日期时间
作为pd进口熊猫
dict_weekday={1:'MON',2:'TUE',3:'WED',4:'THU',5:'FRI',6:'SAT',7:'SUN'}
df=pd.DataFrame(pd.date_范围(datetime.date(2014,1,1),datetime.date(2014,1,15),freq='D'),columns=['date']))
df['Weekday']=df['Date'].apply(lambda x:dict_Weekday[x.isoweekday())
对于df.index中的idx:
打印df.loc[idx,'工作日']

这对我来说似乎是一个bug,作为参考,我使用的是python 3.3.5 64位、pandas 0.15.1和numpy 1.9.1:

您的代码显示,尽管它以字符串形式打印,但数据类型是一个时间戳:

In [56]:

df.iloc[0]['Weekday']
Out[56]:
Timestamp('2014-12-17 00:00:00')
如果我执行以下操作,则它将保持为字符串:

In [58]:

df['Weekday'] = df['Date'].apply(lambda x: dict_weekday[x.isoweekday()])
df['WeekdayInt'] = df['Date'].map(lambda x: x.isoweekday())
df.iloc[0]['Weekday']
Out[58]:
'WED'
In [139]: pd.Series(np.array([pd.Timestamp('2014-01-01 00:00:00'), 'WED'], dtype=object))
Out[139]: 
0   2014-01-01
1   2014-12-17
dtype: datetime64[ns]
上面的内容很奇怪,因为我只添加了第二列

类似地,如果我创建一列来存储int day值,然后执行apply,那么它也可以工作:

In [60]:

df['WeekdayInt'] = df['Date'].map(lambda x: x.isoweekday())
df['Weekday'] = df['WeekdayInt'].apply(lambda x: dict_weekday[x])
df.iloc[0]['Weekday']
Out[60]:
'WED'

如果数据类型是附加的第一列,则它看起来似乎以某种方式持续存在或没有正确分配。

问题不在于
df.loc
df.loc[idx,'Weekday']
正在返回一个序列。 这种令人惊讶的行为是由于pd.Series试图将类似datetime的值转换为时间戳

df.loc[0, 'Weekday']
形成系列

pd.Series(np.array([pd.Timestamp('2014-01-01 00:00:00'), 'WED'], dtype=object))
调用
pd.Series(…)
时,会将其转换为适当的数据类型

如果对代码进行跟踪,您会发现它最终会到达:

检查数据的前几个元素并尝试推断数据类型。 当其中一个值是pd.Timestamp时,Pandas会检查是否所有数据都可以转换为时间戳。实际上,
'Wed'
可以强制转换为pd。时间戳:

In [138]: pd.Timestamp('Wed')
Out[138]: Timestamp('2014-12-17 00:00:00')
这是问题的根源,导致
pd.Series
返回 两个时间戳,而不是一个时间戳和一个字符串:

In [58]:

df['Weekday'] = df['Date'].apply(lambda x: dict_weekday[x.isoweekday()])
df['WeekdayInt'] = df['Date'].map(lambda x: x.isoweekday())
df.iloc[0]['Weekday']
Out[58]:
'WED'
In [139]: pd.Series(np.array([pd.Timestamp('2014-01-01 00:00:00'), 'WED'], dtype=object))
Out[139]: 
0   2014-01-01
1   2014-12-17
dtype: datetime64[ns]
因此,这种情况再次出现

In [140]: df.loc[0, 'Weekday']
Out[140]: Timestamp('2014-12-17 00:00:00')
而不是
“Wed”


备选方案:首先选择系列
df['Weekday']

有许多变通办法;EdChum表明,向样本中添加一个非类日期(整数)值可以防止pd.Series将所有值强制转换为时间戳

df.loc[0, 'Weekday']
或者,您可以在使用
.loc
之前访问
df['Weekdays']

for idx in df.index:
    print df['Weekday'].loc[idx]

备选方案:
df.loc[[idx],“工作日”]

另一种选择是

for idx in df.index:
    print df.loc[[idx], 'Weekday'].item()
df.loc[[idx],'Weekday']
首先选择数据帧
df.loc[[idx]]
。例如,当
idx
等于
0

In [10]: df.loc[[0]]
Out[10]: 
        Date Weekday
0 2014-01-01     WED
df.loc[0]
返回序列:

In [11]: df.loc[0]
Out[11]: 
Date      2014-01-01
Weekday   2014-12-17
Name: 0, dtype: datetime64[ns]
Series尝试将值强制转换为单个有用的数据类型。每个列的数据帧可以有不同的数据类型。因此,
Date
列中的时间戳不会影响
Weekday
列中值的数据类型

因此,通过使用返回数据帧的索引选择器避免了这个问题


备选方案:在工作日使用整数

另一种选择是将isoweekday整数存储在
Weekday
中,并仅在打印结束时转换为字符串:

import datetime
import pandas as pd

dict_weekday = {1: 'MON', 2: 'TUE', 3: 'WED', 4: 'THU', 5: 'FRI', 6: 'SAT', 7: 'SUN'}
df = pd.DataFrame(pd.date_range(datetime.date(2014, 1, 1), datetime.date(2014, 1, 15), freq='D'),   columns=['Date'])
df['Weekday'] = df['Date'].dt.weekday+1   # add 1 for isoweekday

for idx in df.index:
    print dict_weekday[df.loc[idx, 'Weekday']]

备选方案:使用
df.ix

df.loc
是一个
\u LocIndexer
,而
df.ix
是一个
\u IXIndexer
。他们有 不同的
\uu getitem\uu
方法。如果您逐步浏览代码(例如,使用pdb),您会发现:

数据帧方法df.get_value成功返回
'WED'

In [14]: df.get_value(0, 'Weekday')
Out[14]: 'WED'

这就是为什么
df.ix
是在这里工作的另一种选择。

函数工作正常,您会发现您的工作日列实际上是一个时间戳,这就是为什么它看起来很有趣。为什么它是一个时间戳。dict_weekday具有值字符串。顺便说一句,如果我使用.ix而不是.loc,它可以很好地工作,但我认为它也应该适用于。loc@user3176500我不知道,
ix
首先尝试基于标签,然后尝试基于整数,因为您的信息
iloc
也显示了这个错误,所以很奇怪为什么
ix
worksHmm,只是我一个人,还是这真的不是什么大问题?还有一个问题:我可以使用df.loc[idx+1,col_tag]作为例子吗。是首先计算新行索引处理总和,还是实际行索引为“idx+1”。仍然存在两个基本问题:为什么上述情况不起作用,以及如果使用.ix,为什么它起作用?希望熊猫开发者中的某个人看到了这一点,你能试试0.15.2版本并报告吗?在0.15.2版本中仍然会发生这种情况,我认为这很严重,谢谢你的回复。如果我理解正确,这就是.loc的工作方式。与.ix有什么不同?还有,为什么df.loc[[idx],'Weekday'].item()可以工作?这个列表有什么作用?我可以理解df.loc[0]或df.loc['Weekday']返回s系列,但我认为df.loc[0,'Weekday']只返回数据帧的一个元素。你能详细说明一下吗。我会检查你的答案是否正确,因为你给出了详细的解释,但仍然请尝试回答上述问题。谢谢。我添加了一些关于
df.ix
df.loc[[idx],…]如何工作的评论。不幸的是,我对索引器的理解还不够透彻,无法为您提供高级启发式规则,让您了解它们是如何用普通英语工作的。我只能跟踪代码(使用pdb)并在微观层面上找出返回正确或错误值的原因。