Python 熊猫:使用loc在数据帧索引上迭代
我似乎找不到.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
导入日期时间
作为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)并在微观层面上找出返回正确或错误值的原因。