Search code examples
pythonplotlyradar-chartplotly-express

I want to make an animated polar chart but the chart i get only has one radii with a list


med_spotify = spotify_data.drop(columns=['name', 'explicit', 'artists', 'key', 'mode', 'time_signature', 'tempo', 'duration_ms', 'loudness'])    

med_spotify = med_spotify.groupby('release_date').median()
med_spotify = med_spotify.reset_index()
merged = med_spotify['release_date'].to_frame()
merged['theta'] = [med_spotify.columns] * len(merged)
merged['r'] = np.nan
merged['r'] = merged['r'].astype('object')
for k in range(len(merged)):
    merged.at[k, 'r'] = med_spotify.iloc[k].to_list()

fig4 = px.line_polar(merged, r='r', theta='theta', animation_frame='release_date', line_close=True)
fig4.show()

how the plot looks in the browser

I have a dataframe with songs from spotify, then I've made a dataframe with the median of the columns for every year. Now I want to represent that information in a line polar chart animation.

https://medium.com/@marcosanchezayala/plotting-pokemon-attributes-plotly-polar-plots-and-animations-319934b60f0e

This article shows something similar but omits the code that explains how it was done. Changing the theta parameter to a list of column names to use as radii gives an error saying that the length has to be the same as the r parameter. This code shows a empty plot but no errors.

I've tried every way I know to make this work the last two days and searched everywhere in the internet and there's no code examples of px.line_polar charts animated.

Thank you

spotify_data example:

                                  name  duration_ms  explicit  \
0                                Carve       126903         0   
1  Capítulo 2.16 - Banquero Anarquista        98200         0   
2   Vivo para Quererte - Remasterizado       181640         0   
3        El Prisionero - Remasterizado       176907         0   
4                  Lady of the Evening       163080         0   

               artists  release_date  danceability  energy  key  loudness  \
0              ['Uli']          1922         0.645  0.4450    0   -13.338   
1  ['Fernando Pessoa']          1922         0.695  0.2630    0   -22.136   
2  ['Ignacio Corsini']          1922         0.434  0.1770    1   -21.180   
3  ['Ignacio Corsini']          1922         0.321  0.0946    7   -27.961   
4      ['Dick Haymes']          1922         0.402  0.1580    3   -16.900   

   mode  speechiness  acousticness  instrumentalness  liveness  valence  \
0     1       0.4510         0.674            0.7440     0.151    0.127   
1     1       0.9570         0.797            0.0000     0.148    0.655   
2     1       0.0512         0.994            0.0218     0.212    0.457   
3     1       0.0504         0.995            0.9180     0.104    0.397   
4     0       0.0390         0.989            0.1300     0.311    0.196   

     tempo  time_signature  
0  104.851               3  
1  102.009               1  
2  130.418               5  
3  169.980               3  
4  103.220               4  

Solution

  • Since the given data is in wide format, it can be converted to long format to make the data usable for graphing. The data provided was partial data, so I copied the same data and added the year. pd.melt() should refer to this.

    med_spotify = spotify_data.drop(columns=['name', 'explicit', 'artists', 'key', 'mode', 'time_signature', 'tempo', 'duration_ms', 'loudness']) 
    med_spotify = med_spotify.groupby('release_date').median()
    med_spotify.reset_index(inplace=True)
    plot_data = pd.melt(med_spotify, id_vars='release_date', var_name='attribute', value_name='attribute_value')
    
    import plotly.express as px
    
    fig = px.line_polar(plot_data,
                        r='attribute_value', 
                        theta='attribute',
                        line_close=True, 
                        animation_frame = 'release_date',
                        title='Spotify',
                        template = 'ggplot2'
                 )
    fig.update_layout(
        autosize=False,
        height=600,
        width=800,
    )
    
    fig.show()
    

    enter image description here