Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pandas - include all column and row pair values

I have a dataset that is missing a fair amount of data. Example data file:

a,b,c,w
a1,,,
a2,b1,c1,
a2,b1,c2,
a2,,,
a3,b2,c3,
a4,,,
a5,b1,c1,100
a6,b2,c4,
a7,b1,c2,214.285714285714
a7,b1,c2,245.454545454545
a7,b1,c2,292.105263157895
a7,b1,c2,
a8,b1,c2,
a9,b2,c3,
,b3,,
,,c4,
,,c5,

I am struggling to create a pivot table that looks like:

         w
      mean
a       a1  a2  a3  a4     a5  a6          a7  a8  a9
b  c
       NaN NaN NaN NaN    NaN NaN         NaN NaN NaN
b1 c1  NaN NaN NaN NaN  100.0 NaN         NaN NaN NaN
b1 c2  NaN NaN NaN NaN    NaN NaN  250.615174 NaN NaN
b2 c3  NaN NaN NaN NaN    NaN NaN         NaN NaN NaN
b2 c4  NaN NaN NaN NaN    NaN NaN         NaN NaN NaN
b3     NaN NaN NaN NaN    NaN NaN         NaN NaN NaN
   c4  NaN NaN NaN NaN    NaN NaN         NaN NaN NaN
   c5  NaN NaN NaN NaN    NaN NaN         NaN NaN NaN

I don't care if the blanks are at the top or bottom. The key is that every A value appears as a column and for rows, only the existing B,C pairs are displayed.

The following code:

dataframe = pd.read_csv('test/data/sparse.csv')
pd.set_option('display.width', 1000)
print(dataframe)
col_names = ['a']
row_names = ['b', 'c']
value_names = ['w']
aggregates = {'w': ['mean']}

pivot = pd.pivot_table(
    dataframe,
    index=row_names,
    columns=col_names,
    values=value_names,
    aggfunc=aggregates
)

creates a pivot table like:

           w
        mean
a         a5          a7
b  c
b1 c1  100.0         NaN
   c2    NaN  250.615174
b2 c3    NaN         NaN
   c4    NaN         NaN

If I set all None values to blank, via:

for c in dataframe:
    if str(dataframe[c].dtype) in ('object', 'string_', 'unicode_'):
        dataframe[c].fillna(value='', inplace=True)

then I get

           w            
        mean            
a         a5          a7
b  c                    
         NaN         NaN
   c4    NaN         NaN
   c5    NaN         NaN
b1 c1  100.0         NaN
   c2    NaN  250.615174
b2 c3    NaN         NaN
   c4    NaN         NaN
b3       NaN         NaN

which gets me my rows but not my columns. If I add dropna=False to the pivot_table call, then I get all my columns, but I also get row pairs that don't exist in my original data set.

Any suggestions?

Thanks

like image 662
swdevlin Avatar asked Dec 06 '25 02:12

swdevlin


1 Answers

If you're okay with nan instead of blank spaces, then groupby + unstack works here. First, convert columns a, b, and c to string using astype(str). This will cause groupby to no longer ignore NaNs when grouping data.

cols = ['a', 'b', 'c']
df[cols] = df[cols].astype(str)

df.groupby(cols)\
  .w.mean()\
  .unstack(0)\
  .drop('nan', 1)

a        a1  a2  a3  a4     a5  a6          a7  a8  a9
b   c                                                 
b1  c1  NaN NaN NaN NaN  100.0 NaN         NaN NaN NaN
    c2  NaN NaN NaN NaN    NaN NaN  250.615174 NaN NaN
b2  c3  NaN NaN NaN NaN    NaN NaN         NaN NaN NaN
    c4  NaN NaN NaN NaN    NaN NaN         NaN NaN NaN
b3  nan NaN NaN NaN NaN    NaN NaN         NaN NaN NaN
nan c4  NaN NaN NaN NaN    NaN NaN         NaN NaN NaN
    c5  NaN NaN NaN NaN    NaN NaN         NaN NaN NaN
    nan NaN NaN NaN NaN    NaN NaN         NaN NaN NaN
like image 175
cs95 Avatar answered Dec 08 '25 14:12

cs95



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!