Py学习  »  DATABASE

对比 Pandas 和 MySQL 统计直播间各时间段上线人数

CDA数据分析师 • 1 年前 • 150 次点击  

作者:小小明

来源:数据STUDIO


一个数据工作者面试数据相关岗位,SQL查询语句是必不可少的笔试环节,今天云朵君给大家带来了某厂一道面试题,附上参考答案,希望能够帮到大家!  

本文已获作者小小明(CSDN数据处理专家)独家授权
面试题如下:
数据开发

源数据表结构:
room_id(直播间ID)、user_id(上麦用户ID)、start_time(用户上麦开始时间)、end_time(用户上麦结束时间)
该表记录的是每个用户在每个直播间每次上下麦的时间段

目标数据表结构:
room_id(直播间1D)、start_time(用户上麦开始时间)、end_time(用户上麦结束时间)、user_cnt(该时间段内上麦人数)
该表需要记录每个直播间每次人员变动的情况

例子

源数据:

room_iduser_idstart_timeend_time
auser12022-02-01 10:12:132022-02-01 10:30:23
auser22022-02-01 10-21:102022-02-01 11:02:06

目标数据:

room_idstart_timeend_timeuser_cnt
a2022-02-01 10:12:132022-02-01 10:21:101
a2022-02-01 10-21:102022-02-01 10:30:232
a2022-02-01 10:30:232022-02-01 11:02:061
简单理解就是求每个直播间,所有的最短时间段的上线人数。简单图解下:

有了上图,我们应该就秒懂了这题的解题思路,先将所有的时间点排序,按顺序分配得到每个时间分区,绿色为进入起始时间点,红色为结束时间点,我们进入起始点时+1,进入结束时间点时-1,这样就可以得到每个区间的在线人数了。当然假如user3也从10:21:10进去,则这个时间点位置+2,后续的时间片段内在线人数就是累加后的值。

理解了思路,我们就可以开始编码了:

pandas处理代码

最终完整处理代码为:

import pandas as pd

df = pd.DataFrame([
    ["a""user1""2022-02-01 10:12:13""2022-02-01 10:30:23"],
    ["a""user2""2022-02-01 10:21:10""2022-02-01 11:02:06"],
    ["b""user1""2022-02-01 10:12:13""2022-02-01 10:30:23"],
    ["b""user2""2022-02-01 10:21:10""2022-02-01 11:02:06"],
    ["b""user3""2022-02-01 10:19:10""2022-02-01 11:05:06"],
], columns=["room_id""user_id""start_time""end_time"])
df


def func(df):
    times = pd.concat([df.start_time.value_counts(),
                       -df.end_time.value_counts()]).sort_index()
    times.index.name = "start_time"
    r = times.cumsum().to_frame("user_cnt").reset_index()
    r.insert(1"end_time", r.start_time.shift(-1))
    r.insert(0"room_id", df.room_id.iat[0])
    return r.query("user_cnt>0")


df.groupby("room_id", as_index=False).apply(func).reset_index(drop=True)

结果:

注意:使用如下代码即可设置一个单元格可以显示全部输出()




    
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

默认是输出结尾表达式:

from IPython.core.interactiveshell import InteractiveShell
print(InteractiveShell.ast_node_interactivity.default_value)
print(InteractiveShell.ast_node_interactivity.values)
last_expr
['all', 'last', 'last_expr', 'none',
'last_expr_or_assign']

MySQL处理代码

首先我们创建表并插入数据:

CREATE TABLE `t1` (
  `room_id` VARCHAR(20),
  `user_id` VARCHAR(20),
  `start_time` DATETIME,
  `end_time` DATETIME
);

INSERT  INTO `t1`(`room_id`,`user_id`,`start_time`,`end_time`VALUES ('a','user1','2022-02-01 10:12:13','2022-02-01 10:30:23');
INSERT  INTO `t1`(`room_id`,`user_id`,`start_time`,`end_time`VALUES ('a','user2','2022-02-01 10:21:10','2022-02-01 11:02:06');
INSERT  INTO `t1`(`room_id`,`user_id`,`start_time`,`end_time`VALUES ('b','user1','2022-02-01 10:12:13','2022-02-01 10:30:23');
INSERT  INTO `t1`(`room_id`,`user_id`,`start_time`,`end_time`VALUES ('b','user2','2022-02-01 10:21:10','2022-02-01 11:02:06');
INSERT  INTO `t1`(`room_id`,`user_id`,`start_time`,`end_time`VALUES ('b','user3','2022-02-01 10:19:10','2022-02-01 11:05:06');

然后编写SQL:

SELECT
 room_id, start_time, end_time, user_cnt
FROM(
 SELECT
  room_id, start_time,
  lead(start_time) over(PARTITION BY room_id ORDER BY start_time) end_time,
  SUM(i) over(PARTITION BY room_id ORDER BY start_time) user_cnt
 FROM(
  SELECT room_id, start_time, COUNT(1AS i
  FROM t1 GROUP BY room_id, start_time
  UNION ALL 
  SELECT  room_id, end_time, -COUNT(1AS i
  FROM t1 GROUP BY room_id, end_time
 ) a
) b
WHERE user_cnt>0;
OK,问题解决。若读者有更优的解决方案欢迎评论区分享!



 

点这里👇关注我,记得标星哦~



推荐阅读


 

CDA课程咨询

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/137552
 
150 次点击