Baron Yugovich
Baron Yugovich

Reputation: 4307

Pandas dataframe - transform column values into individual columns

I have something like this:

   XY UV  BC   Val
0  y  u    c    11
1  y  u    b    22
2  y  v    c    33
3  y  v    b    44
4  x  u    c    111
5  x  u    b    222
6  x  v    c    333
7  x  v    b    444

I'd like to get

   XY  UV  B_Val  C_Val
0  y   u   22      11
1  y   v   44      33
2  x   u   222    111
3  x   v   444     333

In general, the BC columns above can contain a number of different items, so I need a solution that works in the general case, not only for 2 different values.

I tried writing some code that splits the dataframe, than re-joins the separate parts, but it started looking too complicated, and it wasn't going anywhere.

Upvotes: 1

Views: 1008

Answers (3)

Paul H
Paul H

Reputation: 68146

This where I like to use multi-level indexes and stack/unstack.

So here, I'd do:

from io import StringIO
import pandas

datacsv = StringIO("""\
XY UV  BC   Val
y  u    c    11
y  u    b    22
y  v    c    33
y  v    b    44
x  u    c    111
x  u    b    222
x  v    c    333
x  v    b    444
""")
df = pandas.read_csv(datacsv, sep='\s+')
df.set_index(['XY', 'UV', 'BC']).unstack(level='BC')

Which gives us:

       Val     
BC       b    c
XY UV          
x  u   222  111
   v   444  333
y  u    22   11
   v    44   33

So we have MultiIndexes on both the rows and columns. Assuming you don't want that, I would just do:

xtab = (df.set_index(['XY', 'UV', 'BC'])
          .unstack(level='BC')['Val']
          .reset_index())

And that'll give you:

BC XY UV    b    c
0   x  u  222  111
1   x  v  444  333
2   y  u   22   11
3   y  v   44   33

Upvotes: 2

A Laurent
A Laurent

Reputation: 174

You can also use multi Index and unstack like this:

df=df.set_index(['XY','UV','BC'])
df=df.unstack('BC')

Upvotes: 1

EdChum
EdChum

Reputation: 394041

IIUC you want to pivot:

In [110]:
df.pivot(index='XY',columns='BC', values='Val')

Out[110]:
BC   b   c
XY        
x   10  20
y   33  44

EDIT

pivot doesn't support multi-index df's which was one method I was considering, what you could do is add a new column which is a composite of the 2 columns and use this as the index to pivot on:

In [120]:
df['composite'] = df['XY']+df['UV']
df

Out[120]:
  XY UV BC  Val composite
0  y  u  c   11        yu
1  y  u  b   22        yu
2  y  v  c   33        yv
3  y  v  b   44        yv
4  x  u  c  111        xu
5  x  u  b  222        xu
6  x  v  c  333        xv
7  x  v  b  444        xv

In [121]:
df.pivot(index='composite', columns='BC', values='Val')

Out[121]:
BC           b    c
composite          
xu         222  111
xv         444  333
yu          22   11
yv          44   33

Upvotes: 2

Related Questions