rponthieu dev
rponthieu dev

Reputation: 126

Creating a new pandas dataframe by spliting rows

Let say I have data about cities with the name of the mayor and the baker (if there is one) :

        city name_mayor age_mayor name_baker age_baker
0  Cherbourg     Robert        10       Jack        40
1     Calais     Michel        20     Russel        50
2     Nevers        Guy        30       None      None

I then want to create a new dataframe to work on the individuals, I thus would like a dataframe like so :

        city    name  age
0  Cherbourg  Robert   10
1     Calais  Michel   20
2     Nevers     Guy   30
3  Cherbourg    Jack   40
4     Calais  Russel   50

Then it is easier to compute things such as mean age.

Can anyone tell me :

  1. How can I do so ?
  2. Should I work like that with Pandas ?

Basically I can do it with an iteration over rows, but I read that it is often better to use other ways with pandas (as stated here : How to iterate over rows in a DataFrame in Pandas).

I'm not new to pandas, but still stuck in an "numpy-array" way of thinking.

If needed here are how I made my two example :

data_1 = { "city" : ["Cherbourg", "Calais", "Nevers"], "name_mayor" : ["Robert", "Michel", "Guy"], "age_mayor" : [10,20,30], "name_baker" : ["Jack", "Russel"], "age_baker" : [40,50]}
df_1 = pd.DataFrame.from_dict(data_1, orient='index').transpose()
data_2 = {0:["Cherbourg", "Robert", 10], 1:["Calais", "Michel", 20], 2:["Nevers", "Guy", 30], 3:["Cherbourg", "Jack", 40], 4:["Calais", "Russel", 50]  }
df_2 = pd.DataFrame.from_dict(data_2, orient='index', columns=["city", "name", "age"])

Thanks ! R

Upvotes: 2

Views: 55

Answers (3)

Mateo Lara
Mateo Lara

Reputation: 917

Most of the time when using panda it is better to use its build it methods to modify the array:

import pandas as pd
my_dict = {'city': ['Cherbourg', 'Calais', 'Nevers'], 'name_mayor': ['Robert', 'Michel', 'Guy'],
           'age_mayor': [10, 20, 30], 'name_baker': ['Jack', 'Russel', None], 'age_baker': [40, 50, None]}
my_data_frame = pd.DataFrame(my_dict)
new_data_frame = pd.DataFrame({'city': my_data_frame['city'].append(my_data_frame['city']), 'name': my_data_frame['name_mayor'].append(
    my_data_frame['name_baker']), 'age': my_data_frame['age_mayor'].append(my_data_frame['age_baker'])})
new_data_frame.dropna(inplace=True)
print(new_data_frame)

Output:

        city    name   age
0  Cherbourg  Robert  10.0
1     Calais  Michel  20.0
2     Nevers     Guy  30.0
0  Cherbourg    Jack  40.0
1     Calais  Russel  50.0

Upvotes: 1

NYC Coder
NYC Coder

Reputation: 7594

Here's another way using concat:

df.set_index('city', inplace=True)
df = pd.concat([df[['name_mayor', 'age_mayor']], df[['name_baker', 'age_baker']]]).rename(columns={'name_baker': 'name', 'name_mayor': 'name', 'age_mayor': 'age', 'age_baker': 'age'})
df = df.groupby(level=0, axis=1).first().reset_index()

        city   age    name
0  Cherbourg    10  Robert
1     Calais    20  Michel
2     Nevers    30     Guy
3  Cherbourg    40    Jack
4     Calais    50  Russel
5     Nevers  None    None

Upvotes: 1

BENY
BENY

Reputation: 323226

You can try with pd.wide_to_long

s=pd.wide_to_long(df,['name','age'],i='city',j='drop',sep='_', suffix='\\w+').reset_index()
        city   drop    name   age
0  Cherbourg  mayor  Robert    10
1     Calais  mayor  Michel    20
2     Nevers  mayor     Guy    30
3  Cherbourg  baker    Jack    40
4     Calais  baker  Russel    50
5     Nevers  baker    None  None

s=s[s['name'].ne('None')]

Upvotes: 2

Related Questions