Pandas divide returns dataframe with all NaNs

Viewed 457

I have 2 Pandas Dataframes, totals and medal_counts. The head info is given below.

print(medal_counts.head())

NOC      AFG  AHO  ALG   ANZ  ARG  ARM  AUS   AUT  AZE  BAH  ...  URS  URU  \
Edition                                                      ...             
1896     NaN  NaN  NaN   NaN  NaN  NaN  2.0   5.0  NaN  NaN  ...  NaN  NaN   
1900     NaN  NaN  NaN   NaN  NaN  NaN  5.0   6.0  NaN  NaN  ...  NaN  NaN   
1904     NaN  NaN  NaN   NaN  NaN  NaN  NaN   1.0  NaN  NaN  ...  NaN  NaN   
1908     NaN  NaN  NaN  19.0  NaN  NaN  NaN   1.0  NaN  NaN  ...  NaN  NaN   
1912     NaN  NaN  NaN  10.0  NaN  NaN  NaN  14.0  NaN  NaN  ...  NaN  NaN   

NOC        USA  UZB  VEN  VIE  YUG  ZAM  ZIM   ZZX  
Edition                                             
1896      20.0  NaN  NaN  NaN  NaN  NaN  NaN   6.0  
1900      55.0  NaN  NaN  NaN  NaN  NaN  NaN  34.0  
1904     394.0  NaN  NaN  NaN  NaN  NaN  NaN   8.0  
1908      63.0  NaN  NaN  NaN  NaN  NaN  NaN   NaN  
1912     101.0  NaN  NaN  NaN  NaN  NaN  NaN   NaN  
[5 rows x 138 columns]

print(totals.head())

Edition
1896    151
1900    512
1904    470
1908    804
1912    885
Name: Grand Total, dtype: int64

When I try divide 'medal_counts' using 'totals' row-wise using divide method, why I am getting all NaNs though there are some clear values in medal_counts, such as in 1896 for AUS, AUT, USA & ZZX.

fractions = medal_counts.divide(totals, axis='rows')

print(fractions.head())

NOC      AFG  AHO  ALG  ANZ  ARG  ARM  AUS  AUT  AZE  BAH  ...  URS  URU  USA  \
Edition                                                    ...                  
1896     NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  ...  NaN  NaN  NaN   
1900     NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  ...  NaN  NaN  NaN   
1904     NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  ...  NaN  NaN  NaN   
1908     NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  ...  NaN  NaN  NaN   
1912     NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  ...  NaN  NaN  NaN   

NOC      UZB  VEN  VIE  YUG  ZAM  ZIM  ZZX  
Edition                                     
1896     NaN  NaN  NaN  NaN  NaN  NaN  NaN  
1900     NaN  NaN  NaN  NaN  NaN  NaN  NaN  
1904     NaN  NaN  NaN  NaN  NaN  NaN  NaN  
1908     NaN  NaN  NaN  NaN  NaN  NaN  NaN  
1912     NaN  NaN  NaN  NaN  NaN  NaN  NaN  

Appreciate clarifications.

2 Answers

When you use pandas divide:

df.divide(other)

The type of other can be : scalar, sequence, Series, or DataFrame.

In your case, if you would specify a series it would work:

fractions = medal_counts.divide(totals['Edition'], axis='rows')

So, when should we use dataframe?

If you the other dataframe`s shape is the same as df. For example:

df = pd.DataFrame({'angles': [0, 3, 4],
                   'degrees': [360, 180, 360]},
                  index=['circle', 'triangle', 'rectangle'])
df
           angles  degrees
circle          0      360
triangle        3      180
rectangle       4      360

you can do:

>>> df.divide(df+1, axis='index')

           angles   degrees
circle       0.00  0.997230
triangle     0.75  0.994475
rectangle    0.80  0.997230

Why converting to numpy array is not safe?

If your rows are shuffled you will get the wrong answer:

df
           angles  degrees
circle          0      360
triangle        3      180
rectangle       4      360

shuffle the angles column and create a new df:

df2 = df[['angles']].sample(frac=1)
df2
           angles
triangle        3
circle          0
rectangle       4

The desired output:

>>> df.divide(df2['angles'], axis='rows')
           angles  degrees
circle        NaN      inf
rectangle     1.0     90.0
triangle      1.0     60.0

and the output using numpy array:

>>> df.divide(df2['angles'].values, axis='rows')
           angles  degrees
circle        0.0    120.0
triangle      inf      inf
rectangle     1.0     90.0

Below transformation works.

totals = totals.values
fractions = medal_counts.divide(totals, axis='rows')
Related