Skip to main content
Back to problems
#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)
LeetCode
solution.pandas
# 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])