简体   繁体   中英

How to change values (that are lists) in python Data Frame based on condition?

I have a DataFrame 'songDataFrame' with information about songs. There are three columns: 'artist', 'title', 'genres' . The first two are string and 'genres' contains lists of genres. It looks like this:

id  artist             title         genres
1   'Sarah Bareilles'  'Opening Up'  ['acoustic','pop', 'piano']
2   'Post Malone'      'Stay'        ['Hip-Hop', 'rap', 'trap']
3   'Dean Lewis'       'Waves'       ['alternative', 'guitar', 'indie']
4   'Billie Eilish'    'Watch'       ['indie', 'indie pop', 'pop']
5   'Passenger'        'Let Her Go'  ['metal', 'screamo', 'gore']

Genres for artist 'Passenger' are wrong. I want to change the existing list to ['indie rock', 'folk rock'].

If it wasn't a list, but I was replacing with a string I would just do:

mask = songDataFrame.artist =='Passenger'
songDataFrame.loc[mask, 'genres'] = 'indie folk'

This way it works fine. When instead of 'indie folk' I put ['indie rock', 'folk rock'],

mask = songDataFrame.artist =='Passenger'
songDataFrame.loc[mask, 'genres'] = ['indie folk','folk rock']

I get this error:

ValueError: Must have equal len keys and value when setting with an iterable

Is there a way to solve that?

Use two-lines and use loc for assigning a string, make all column values string, then make them back to list:

import ast
songDataFrame.loc[songDataFrame['artist']=='Passenger','genres']="['indie folk','folk rock']"
songDataFrame['genres']=songDataFrame['genres'].astype(str).apply(ast.literal_eval)

And now:

print(songDataFrame)

Is:

   id           artist       title                        genres
0   1  Sarah Bareilles  Opening Up        [acoustic, pop, piano]
1   2      Post Malone        Stay          [Hip-Hop, rap, trap]
2   3       Dean Lewis       Waves  [alternative, guitar, indie]
3   4    Billie Eilish       Watch       [indie, indie pop, pop]
4   5        Passenger  Let Her Go       [indie folk, folk rock]

Without the extra package and the literal_eval trick:

mask = (songDataFrame.artist == 'Passenger').tolist().index(True)
songDataFrame.at[mask, 'genres'] = ['indie folk','folk rock']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM