Usuarios activos en los últimos 30 dÃas I
Escribe una solución para encontrar el total de usuarios activos durante un periodo de 30 dÃas terminando el 2019-07-27 (incluyendo esta fecha). Un usuario estuvo activo si hizo al menos una actividad en ese dÃa. Regresa el resultado en cualquier orden.
Tabla: Activity
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| user_id | int |
| session_id | int |
| activity_date | date |
| activity_type | enum |
+---------------+---------+
- Esta tabla puede contener filas duplicadas.
- La columna activity_type es un ENUM (categorÃa) de tipo ('open_session', 'end_session', 'scroll_down', 'send_message').
- La tabla muestra la actividad de cada usuario en una red social.
- Nota que cada sesión pertenece a exactamente un usuario.
El formato del resultado se muestra en el siguiente ejemplo.
Ejemplo 1:
Entrada:
Tabla Activity:
+---------+------------+---------------+---------------+
| user_id | session_id | activity_date | activity_type |
+---------+------------+---------------+---------------+
| 1 | 1 | 2019-07-20 | open_session |
| 1 | 1 | 2019-07-20 | scroll_down |
| 1 | 1 | 2019-07-20 | end_session |
| 2 | 4 | 2019-07-20 | open_session |
| 2 | 4 | 2019-07-21 | send_message |
| 2 | 4 | 2019-07-21 | end_session |
| 3 | 2 | 2019-07-21 | open_session |
| 3 | 2 | 2019-07-21 | send_message |
| 3 | 2 | 2019-07-21 | end_session |
| 4 | 3 | 2019-06-25 | open_session |
| 4 | 3 | 2019-06-25 | end_session |
+---------+------------+---------------+---------------+
Salida:
+------------+--------------+
| day | active_users |
+------------+--------------+
| 2019-07-20 | 2 |
| 2019-07-21 | 2 |
+------------+--------------+
Explicación: Nota que los dÃas sin usuarios activos no son relevantes para esta consulta.
Solución:
import datetime
import pandas as pd
def user_activity(activity: pd.DataFrame) -> pd.DataFrame:
# `between` end date is not inclusive 27+1
period_end = datetime.datetime(2019, 7, 28)
period_start = period_end - pd.Timedelta('30D')
df = activity[activity.activity_date.between(period_start, period_end)]
no_duplicates = (
~df.duplicated(['user_id', 'activity_date']),
)
result = df.loc[no_duplicates].groupby(
'activity_date'
).size().reset_index(name='active_users')
return pd.DataFrame({
'day': result['activity_date'],
'active_users': result['active_users']
})
def test_user_activity():
data = [
[1, 1, '2019-07-20', 'open_session'],
[1, 1, '2019-07-20', 'scroll_down'],
[1, 1, '2019-07-20', 'end_session'],
[2, 4, '2019-07-20', 'open_session'],
[2, 4, '2019-07-21', 'send_message'],
[2, 4, '2019-07-21', 'end_session'],
[3, 2, '2019-07-21', 'open_session'],
[3, 2, '2019-07-21', 'send_message'],
[3, 2, '2019-07-21', 'end_session'],
[4, 3, '2019-06-25', 'open_session'],
[4, 3, '2019-06-25', 'end_session']
]
activity = pd.DataFrame(
data,
columns=['user_id', 'session_id', 'activity_date', 'activity_type']
).astype({
'user_id': 'Int64',
'session_id': 'Int64',
'activity_date': 'datetime64[ns]',
'activity_type': 'object'
})
expected = pd.DataFrame(
[['2019-07-20', 2], ['2019-07-21', 2]],
columns=['day', 'active_users']
).astype({
'day': 'datetime64[ns]',
'active_users': 'int'
})
got = user_activity(activity)
pd.testing.assert_frame_equal(expected, got)