我在从多索引的pandas数据帧快速删除行时遇到问题,其中丢弃标准基于1级索引。或者等效地,通过附加单索引数据帧或numpy数组作为行来构建多索引数据帧。在我的具体例子中,我有一个名为“watch”的数据框,如下所示:
userid watchers
repositoryid date
5910995 1348293168 1449180 1
5911012 1348292421 2627657 1
5911046 1367171000 1219404 1
1368722792 1892225 2
1383586883 2150178 3
5911088 1348302179 1521780 1
...
其中,repositoryid和date分别是multiindex的级别0和1,userid和watchers是数据列。因此,对于每个repositoryid,我基本上都有一系列用户开始观看存储库的事件。对于每个repositoryid,我也知道来自其他地方的特定创建日期。现在我想删除日期>的所有行creationdate + timewindow,其中timewindow是常量。
我尝试使用drop()函数,但这非常慢。我认为布尔屏蔽将是最好的解决方案,但我无法使其与多索引一起使用。我也尝试过几次尝试从头开始构建一个新的数据框架,最新的一个就是:
watch_new = DataFrame(columns=['date', 'userid', 'watchers'])
for i,rid in enumerate(watch.index.get_level_values('repositoryid')):
creationdate = repository.loc[rid].date.squeeze()
thistimeseries = watch.loc[rid]
thistimeseries = thistimeseries[thistimeseries.index <= creationdate+timewindow]
thistimeseries.reset_index(inplace=True)
if len(thistimeseries) != 0:
watch_new.loc[rid] = thistimeseries.as_matrix()
不幸的是,只要thistimeseries.as_matrix()有多行,我就会收到一条错误消息,例如(在这种情况下,10行):
ValueError: could not broadcast input array from shape (10,3) into shape (3)
所以,我的问题是,1a)如何从多级索引数据帧中快速删除行,条件是1级索引,或等效地1b)如何将单索引数据帧插入多索引数据帧,2)这是解决我问题的最佳=最快的方式,还是应该尝试完全不同的方法?
(我也尝试不使用索引,但这太慢了。我玩加入,合并,分组等等,不幸的是我无法让他们解决我的问题。我花了最近5天学习这本优秀的书籍“Python for Data Analysis”并尝试在线找到这个问题的解决方案,但又没有成功。我希望高级熊猫用户可以为这个看似简单的问题提供优雅的解决方案吗?非常感谢!)
答案 0 :(得分:0)
从此设置开始:
import pandas as pd
df = pd.read_table('data', sep='\s+').set_index(['repositoryid', 'date'])
repository = pd.read_table('data2', sep='\s+').set_index(['repositoryid'])
timewindow = 100
假设我们有df
:
userid watchers
repositoryid date
5910995 1348293168 1449180 1
5911012 1348292421 2627657 1
5911046 1367171000 1219404 1
1368722792 1892225 2
1383586883 2150178 3
5911088 1348302179 1521780 1
和repository
:
date
repositoryid
5910995 1348293200
5911012 1348292400
5911046 1368722800
5911088 1348303000
目前,Pandas不支持仅合并MultiIndex的某些级别。因此,df
和repository
必须具有相同的索引形状才能合并:
df.reset_index(level='date', inplace=True)
df = df.join(repository, rsuffix='_threshold')
产量
date userid watchers date_threshold
repositoryid
5910995 1348293168 1449180 1 1348293200
5911012 1348292421 2627657 1 1348292400
5911046 1367171000 1219404 1 1368722800
5911046 1368722792 1892225 2 1368722800
5911046 1383586883 2150178 3 1368722800
5911088 1348302179 1521780 1 1348303000
现在您可以将timewindow
添加到date_threshold
:
df['date_threshold'] += timewindow
并在date
小于date_threshold
:
mask = df['date'] < df['date_threshold']
产生类似
的布尔系列In [207]: mask
Out[207]:
repositoryid
5910995 True
5911012 True
5911046 True
5911046 True
5911046 False
5911088 True
dtype: bool
使用布尔系列,可以使用df.loc
:
In [208]: df.loc[mask]
Out[208]:
date userid watchers date_threshold
repositoryid
5910995 1348293168 1449180 1 1348293300
5911012 1348292421 2627657 1 1348292500
5911046 1367171000 1219404 1 1368722900
5911046 1368722792 1892225 2 1368722900
5911088 1348302179 1521780 1 1348303100
或者,您可以使用mask
代替df.loc
和query
:
In [213]: df.query('date < date_threshold')
Out[213]:
date userid watchers date_threshold
repositoryid
5910995 1348293168 1449180 1 1348293300
5911012 1348292421 2627657 1 1348292500
5911046 1367171000 1219404 1 1368722900
5911046 1368722792 1892225 2 1368722900
5911088 1348302179 1521780 1 1348303100