Explode a row to multiple rows in pandas dataframe

不打扰是莪最后的温柔 提交于 2019-12-11 01:54:14

问题


I have a dataframe with the following header:

id, type1, ..., type10, location1, ..., location10

and I want to convert it as follows:

id, type, location 

I managed to do this using embedded for loops but it's very slow:

new_format_columns = ['ID', 'type', 'location'] 
new_format_dataframe = pd.DataFrame(columns=new_format_columns)



print(data.head())
new_index = 0 
for index, row in data.iterrows(): 
        ID = row["ID"]

        for i in range(1,11):
                if row["type"+str(i)] == np.nan:
                        continue
                else:
                        new_row = pd.Series([ID, row["type"+str(i)], row["location"+str(i)]])
                        new_format_dataframe.loc[new_index] = new_row.values
                        new_index += 1

Any suggestions for improvement using native pandas features?


回答1:


You can use lreshape:

types = [col for col in df.columns if col.startswith('type')]
location = [col for col in df.columns if col.startswith('location')]

print(pd.lreshape(df, {'Type':types, 'Location':location}, dropna=False))

Sample:

import pandas as pd

df = pd.DataFrame({
'type1': {0: 1, 1: 4}, 
'id': {0: 'a', 1: 'a'}, 
'type10': {0: 1, 1: 8},
'location1': {0: 2, 1: 9},
'location10': {0: 5, 1: 7}})

print (df)
  id  location1  location10  type1  type10
0  a          2           5      1       1
1  a          9           7      4       8

types = [col for col in df.columns if col.startswith('type')]
location = [col for col in df.columns if col.startswith('location')]

print(pd.lreshape(df, {'Type':types, 'Location':location}, dropna=False))
  id  Location  Type
0  a         2     1
1  a         9     4
2  a         5     1
3  a         7     8

Another solution with double melt:

print (pd.concat([pd.melt(df, id_vars='id', value_vars=types, value_name='type'),
                  pd.melt(df, value_vars=location, value_name='Location')], axis=1)
         .drop('variable', axis=1))

  id  type  Location
0  a     1         2
1  a     4         9
2  a     1         5
3  a     8         7

EDIT:

lreshape is now undocumented, but is possible in future will by removed (with pd.wide_to_long too).

Possible solution is merging all 3 functions to one - maybe melt, but now it is not implementated. Maybe in some new version of pandas. Then my answer will be updated.



来源:https://stackoverflow.com/questions/39853311/explode-a-row-to-multiple-rows-in-pandas-dataframe

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!