#3808
Medium Database Find emotionally consistent users
51.8% acceptance
Mar 17, 2026
28
1
Table: reactions
+--------------+---------+
| Column Name | Type |
+--------------+---------+
| user_id | int |
| content_id | int |
| reaction | varchar |
+--------------+---------+
(user_id, content_id) is the primary key (unique value) for this table.
Each row represents a reaction given by a user to a piece of content.
Write a solution to identify emotionally consistent users based on the following requirements:
For each user, count the total number of reactions they have given.
Only include users who have reacted to at least 5 different content items.
A user is considered emotionally consistent if at least 60% of their reactions are of the same type.
Return the result table ordered by reaction_ratio in descending order and then by user_id in ascending order.
Note:
reaction_ratio should be rounded to 2 decimal places
The result format is in the following example.
Solution
Pandas
Time O(n)
Space O(1)
# Table: reactions
#
# +--------------+---------+
# | Column Name | Type |
# +--------------+---------+
# | user_id | int |
# | content_id | int |
# | reaction | varchar |
# +--------------+---------+
# (user_id, content_id) is the primary key (unique value) for this table.
# Each row represents a reaction given by a user to a piece of content.
#
# Write a solution to identify emotionally consistent users based on the following requirements:
#
# For each user, count the total number of reactions they have given.
#
# Only include users who have reacted to at least 5 different content items.
#
# A user is considered emotionally consistent if at least 60% of their reactions are of the same type.
#
# Return the result table ordered by reaction_ratio in descending order and then by user_id in ascending order.
#
# Note:
#
# reaction_ratio should be rounded to 2 decimal places
#
# The result format is in the following example.
#
# Example 1:
# Input:
# reactions table:
# +---------+------------+----------+
# | user_id | content_id | reaction |
# +---------+------------+----------+
# | 1 | 101 | like |
# | 1 | 102 | like |
# | 1 | 103 | like |
# | 1 | 104 | wow |
# | 1 | 105 | like |
# | 2 | 201 | like |
# | 2 | 202 | wow |
# | 2 | 203 | sad |
# | 2 | 204 | like |
# | 2 | 205 | wow |
# | 3 | 301 | love |
# | 3 | 302 | love |
# | 3 | 303 | love |
# | 3 | 304 | love |
# | 3 | 305 | love |
# +---------+------------+----------+
# Output:
# +---------+-------------------+----------------+
# | user_id | dominant_reaction | reaction_ratio |
# +---------+-------------------+----------------+
# | 3 | love | 1.00 |
# | 1 | like | 0.80 |
# +---------+-------------------+----------------+
# Explanation:
# User 1:
# Total reactions = 5
# like appears 4 times
# reaction_ratio = 4 / 5 = 0.80
# Meets the 60% consistency requirement
# User 2:
# Total reactions = 5
# Most frequent reaction appears only 2 times
# reaction_ratio = 2 / 5 = 0.40
# Does not meet the consistency requirement
# User 3:
# Total reactions = 5
# 'love' appears 5 times
# reaction_ratio = 5 / 5 = 1.00
# Meets the consistency requirement
# The Results table is ordered by reaction_ratio in descending order, then by user_id in ascending order.
#
# Example 2:
# Input:
# reactions table:
# +---------+------------+----------+
# | user_id | content_id | reaction |
# +---------+------------+----------+
# | 1 | 1 | wow |
# | 1 | 2 | wow |
# | 1 | 3 | sad |
# | 1 | 4 | like |
# | 1 | 5 | like |
# | 2 | 6 | sad |
# | 2 | 7 | sad |
# | 2 | 8 | like |
# | 2 | 9 | like |
# | 2 | 10 | sad |
# | 2 | 11 | sad |
# | 2 | 12 | sad |
# | 2 | 13 | sad |
# | 2 | 14 | like |
# | 2 | 15 | sad |
# | 3 | 16 | like |
# | 3 | 17 | sad |
# | 3 | 18 | sad |
# | 3 | 19 | wow |
# | 3 | 20 | angry |
# | 3 | 21 | love |
# | 3 | 22 | wow |
# | 3 | 23 | wow |
# | 3 | 24 | love |
# | 3 | 25 | wow |
# | 4 | 26 | angry |
# | 4 | 27 | like |
# | 5 | 28 | angry |
# | 5 | 29 | wow |
# | 5 | 30 | wow |
# | 5 | 31 | love |
# | 5 | 32 | angry |
# | 6 | 33 | like |
# | 6 | 34 | angry |
# | 6 | 35 | love |
# | 6 | 36 | like |
# | 6 | 37 | like |
# | 6 | 38 | wow |
# | 6 | 39 | like |
# | 6 | 40 | like |
# | 7 | 41 | wow |
# | 7 | 42 | angry |
# | 7 | 43 | love |
# | 7 | 44 | wow |
# | 7 | 45 | love |
# | 7 | 46 | like |
# | 7 | 47 | love |
# +---------+------------+----------+
# Output:
# +---------+-------------------+----------------+
# | user_id | dominant_reaction | reaction_ratio |
# +---------+-------------------+----------------+
# | 2 | sad | 0.70 |
# | 6 | like | 0.63 |
# +---------+-------------------+----------------+
# Explanation:
# User 2: total=10, sad=7, ratio=7/10=0.70
# User 6: total=8, like=5, ratio=5/8=0.625 -> rounds to 0.63
import math
import pandas as pd
def find_emotionally_consistent_users(reactions: pd.DataFrame) -> pd.DataFrame:
total = reactions.groupby('user_id').size().reset_index(name='total')
total = total[total['total'] >= 5]
reaction_counts = reactions.groupby(['user_id', 'reaction']).size().reset_index(name='count')
dominant = reaction_counts.loc[reaction_counts.groupby('user_id')['count'].idxmax()]
result = dominant.merge(total, on='user_id')
result['reaction_ratio'] = result.apply(
lambda row: math.floor(row['count'] / row['total'] * 100 + 0.5) / 100, axis=1
)
result = result[result['reaction_ratio'] >= 0.60]
return result.rename(columns={'reaction': 'dominant_reaction'})[['user_id', 'dominant_reaction', 'reaction_ratio']].sort_values(['reaction_ratio', 'user_id'], ascending=[False, True])