Reputation: 65
I have a dictionary Songs
with songs as the keys and their moods as values. I also have a Users
dictionary with listened songs. I would now like to check what moods from the Songs
dictionary are most prevalent for each user and put those moods in a new dictionary coupling user to the mood. This is what I have right now:
from collections import Counter
Songs = {
'Song1' : ['techno', 'upbeat'],
'Song2' : ['rock', 'upbeat'],
'Song3' : ['pop', 'sad'],
'Song5' : ['pop', 'calm'],
'Song6' : ['rap', 'upbeat'],
'Song7' : ['rock', 'sad']
}
Users = {
'User1' : ['Song1', 'Song2', 'Song6'],
'User2' : ['Song3', 'Song7'],
'User3' : ['Song2', 'Song7']
}
Users_moods = dict.fromkeys(Users)
for user, song in Users.items():
for song, mood in Songs.items():
mood = set(mood)
mood_counter = Songs[song]
Users_moods = {user: counter.most_common(1)[0][0] for user, counter in Users.items()}
print(Users_moods)
print(Songs)
print(Users)
But it gives me errors. This is what the Users_mood
dictionary should look like for this example:
Users_moods = {
'User1' : 'upbeat',
'User2' : 'sad',
'User3' : 'rock'
}
Upvotes: 0
Views: 62
Reputation: 5871
If you intend to use collections.Counter, let's look at https://docs.python.org/3/library/collections.html#collections.Counter You're going to need
mood_counter = Counter(iterable)
Presumably, iterable here comes from looking at one user, then all their songs, then all the moods from those songs. Rather than try to make a one liner, let's just iterate over those normally.
def get_user_mood(user, Users, Songs):
accumulated_moods = []
for song_name in Users[user]:
moods_for_this_song = Songs[song_name]
accumulated_moods.extend(moods_for_this_song)
mood_counter = Counter(accumulated_moods)
return mood_counter.most_common(1)[0][0] # validate?
This allows you to build the dict fairly easily in a comprehension
Users_moods = {user: get_user_mood(user, Users, Songs) for user in Users}
Upvotes: 0
Reputation: 113915
def getMoods(user, users, songs):
userSongs = users[user] # songs this user listens to
moods = {} # count of each mood this user listens to
for song in userSongs:
for mood in songs[song]: # for each mood of that song
moods.setdefault(mood, 0)
moods[mood] += 1
return max(moods, key=moods.get) # the most prevalent mood
for user in users:
print(user, 'likes', getMoods(user, users, songs)) # mood with the highest count
Upvotes: 2
Reputation: 19403
You're not actually using Counter
and trying to call most_common
on a list. Let's try to break it down:
To better handle 1, we can use a defaultdict
:
from collections import Counter, defaultdict
Users_moods = defaultdict(list)
for user, songs in Users.items():
for song in songs:
Users_moods[user].extend(Songs[song])
common_moods = {user: Counter(moods).most_common(1)[0][0] for user, moods in Users_moods.items()}
print(Users_moods)
print(common_moods)
This gives:
defaultdict(<class 'list'>, {'User1': ['techno', 'upbeat', 'rock', 'upbeat', 'rap', 'upbeat'], 'User2': ['pop', 'sad', 'rock', 'sad'], 'User3': ['rock', 'upbeat', 'rock', 'sad']})
{'User1': 'upbeat', 'User2': 'sad', 'User3': 'rock'}
Alternatively, you can build the common
dict on-the-fly with the same loop, by creating a separate Counter
for each user:
common_moods = {}
for user, songs in Users.items():
User_moods = Counter()
for song in songs:
User_moods += Counter(Songs[song])
common_moods[user] = User_moods.most_common(1)[0][0]
print(common_moods)
Upvotes: 1