我正在努力寻找一种“简单”的方式来对熊猫进行这种分析:
我有xlsx文件,该文件显示了人们进入建筑物的过程。 在这里,我显示了原始数据的简化版本。
Full Name Time Direction
0 Uncle Scrooge 08-10-2018 09:16:52 In
1 Uncle Scrooge 08-10-2018 16:42:40 Out
2 Donald Duck 08-10-2018 15:04:07 In
3 Donald Duck 08-10-2018 15:06:42 Out
4 Donald Duck 08-10-2018 15:15:49 In
5 Donald Duck 08-10-2018 16:07:57 Out
我理想的最终结果是以表格或更好的图形方式显示建筑物总人数随时间变化的情况。 所以回到我提供的示例数据,我想证明一下在2018年8月10日这一天:
在该示例中,我使用了真实数据,因此您可以看到时间戳精确到秒,但是我并不需要那么精确,因为该分析必须在2个月的范围内进行。
感谢您的帮助
非常感谢
乔治
================ 更新:===============
@nixon和@ALollz非常感谢您。 它非常完美,除了我最初提出的问题中没有想到的细节。
事实上,正如我所提到的,我正在处理两个月的数据。 而且,由于某种原因,似乎并不是所有进入建筑物的人在离开建筑物时都被追踪到。 因此,使用cumsum()函数,我发现一天中的总人数受到前一天的人们的影响,依此类推, 这表明,除了最初的几天外,在每天的清晨和傍晚都有大量人员进入该建筑物。
因此,我认为可以通过先在几天内执行group_by然后应用您的建议来解决此问题。
您能帮我把一切放在一起吗? 非常感谢
乔治
答案 0 :(得分:0)
您可以首先将Time
列设置为索引,然后使用sort_index
对其进行排序:
df = df.set_index('Time').sort_index()
print(df)
Direction Full Name
Time
2018-08-10 09:16:52 In Uncle Scrooge
2018-08-10 15:04:07 In Donald Duck
2018-08-10 15:06:42 Out Donald Duck
2018-08-10 15:15:49 In Donald Duck
2018-08-10 16:07:57 Out Donald Duck
2018-08-10 16:42:40 Out Uncle Scrooge
并创建{'In':1, 'Out':-1}
的映射(如@ALollz建议):
mapper = {'In':1, 'Out':-1}
df = df.assign(Direction_mapped = df.Direction.map(mapper))
哪个会给你:
Direction Full Name Direction_mapped
Time
2018-08-10 09:16:52 In Uncle Scrooge 1
2018-08-10 15:04:07 In Donald Duck 1
2018-08-10 15:06:42 Out Donald Duck -1
2018-08-10 15:15:49 In Donald Duck 1
2018-08-10 16:07:57 Out Donald Duck -1
2018-08-10 16:42:40 Out Uncle Scrooge -1
已经映射了“方向”列,您可以简单地将cumsum
应用于结果,这将为您提供从特定时间开始的人数:
df = df.assign(n_people = df.Direction_mapped.cumsum()).drop(['Direction_mapped'], axis = 1)
哪种产量:
Direction Full Name n_people
Time
2018-08-10 09:16:52 In Uncle Scrooge 1
2018-08-10 15:04:07 In Donald Duck 2
2018-08-10 15:06:42 Out Donald Duck 1
2018-08-10 15:15:49 In Donald Duck 2
2018-08-10 16:07:57 Out Donald Duck 1
2018-08-10 16:42:40 Out Uncle Scrooge 0
针对并非所有人都被跟踪离开建筑物的情况的更通用解决方案。让我们尝试一个包含多于一天的新df。还让我们模拟这次唐纳德·达克(Donald Duck)确实进过两次,但是第二次却没有被跟踪到进去。
df = pd.DataFrame({'Full Name': ['Uncle Scrooge','Uncle Scrooge', 'Donald Duck', 'Donald Duck', 'Donald Duck',
'Someone else', 'Someone else'],
'Time': ['08-10-2018 09:16:52','08-10-2018 16:42:40', '08-10-2018 15:04:07', '08-10-2018 15:06:42', '08-10-2018 15:15:49',
'08-11-2018 10:42:40', '08-11-2018 10:48:40'],
'Direction': ['In','Out','In','Out', 'In','In', 'Out']})
print(df)
Full Name Time Direction
0 Uncle Scrooge 08-10-2018 09:16:52 In
1 Uncle Scrooge 08-10-2018 16:42:40 Out
2 Donald Duck 08-10-2018 15:04:07 In
3 Donald Duck 08-10-2018 15:06:42 Out
4 Donald Duck 08-10-2018 15:15:49 In
5 Someone else 08-11-2018 10:42:40 In
6 Someone else 08-11-2018 10:48:40 Out
首先,可以将先前的功能封装在一个函数中
def apply_by_day(x):
mapper = {'In':1, 'Out':-1}
x = x.assign(Direction_mapped = x.Direction.map(mapper))
x = x.assign(n_people = x.Direction_mapped.cumsum())\
.drop(['Direction_mapped'], axis = 1)
return x
然后可以使用pandas.Grouper
将apply_by_day
应用于日常组:
df.Time = pd.to_datetime(df.Time)
df = df.set_index('Time').sort_index()
df.groupby(pd.Grouper(freq='D')).apply(lambda x: apply_by_day(x))
Full Name Direction n_people
Time Time
2018-08-10 2018-08-10 09:16:52 Uncle Scrooge In 1
2018-08-10 15:04:07 Donald Duck In 2
2018-08-10 15:06:42 Donald Duck Out 1
2018-08-10 15:15:49 Donald Duck In 2
2018-08-10 16:42:40 Uncle Scrooge Out 1
2018-08-11 2018-08-11 10:42:40 Someone else In 1
2018-08-11 10:48:40 Someone else Out 0
如结果数据框所示,即使没有被追踪到2018-08-10离开建筑物,n_people仍会在第二天从0开始,因为每天分别应用定义的功能。