pandas 遍历并修改_遍历行并扩展pandas数据框

I have pandas dataframe with a column containing values or lists of values (of unequal length). I want to 'expand' the rows, so each value in the list becomes single value in column. An example says it all:

dfIn = pd.DataFrame({u'name': ['Tom', 'Jim', 'Claus'],

u'location': ['Amsterdam', ['Berlin','Paris'], ['Antwerp','Barcelona','Pisa'] ]})

location name

0 Amsterdam Tom

1 [Berlin, Paris] Jim

2 [Antwerp, Barcelona, Pisa] Claus

I want to turn into:

dfOut = pd.DataFrame({u'name': ['Tom', 'Jim', 'Jim', 'Claus','Claus','Claus'],

u'location': ['Amsterdam', 'Berlin','Paris', 'Antwerp','Barcelona','Pisa']})

location name

0 Amsterdam Tom

1 Berlin Jim

2 Paris Jim

3 Antwerp Claus

4 Barcelona Claus

5 Pisa Claus

I first tried using apply but it's not possible to return multiple Series as far as I know. iterrows seems to be the trick. But the code below gives me an empty dataframe...

def duplicator(series):

if type(series['location']) == list:

for location in series['location']:

subSeries = series

subSeries['location'] = location

dfOut.append(subSeries)

else:

dfOut.append(series)

for index, row in dfIn.iterrows():

duplicator(row)

解决方案

If you return a series whose index is a list of locations, then dfIn.apply will collate those series into a table:

import pandas as pd

dfIn = pd.DataFrame({u'name': ['Tom', 'Jim', 'Claus'],

u'location': ['Amsterdam', ['Berlin','Paris'],

['Antwerp','Barcelona','Pisa'] ]})

def expand(row):

locations = row['location'] if isinstance(row['location'], list) else [row['location']]

s = pd.Series(row['name'], index=list(set(locations)))

return s

In [156]: dfIn.apply(expand, axis=1)

Out[156]:

Amsterdam Antwerp Barcelona Berlin Paris Pisa

0 Tom NaN NaN NaN NaN NaN

1 NaN NaN NaN Jim Jim NaN

2 NaN Claus Claus NaN NaN Claus

You can then stack this DataFrame to obtain:

In [157]: dfIn.apply(expand, axis=1).stack()

Out[157]:

0 Amsterdam Tom

1 Berlin Jim

Paris Jim

2 Antwerp Claus

Barcelona Claus

Pisa Claus

dtype: object

This is a Series, while you want a DataFrame. A little massaging with reset_index gives you the desired result:

dfOut = dfIn.apply(expand, axis=1).stack()

dfOut = dfOut.to_frame().reset_index(level=1, drop=False)

dfOut.columns = ['location', 'name']

dfOut.reset_index(drop=True, inplace=True)

print(dfOut)

yields

location name

0 Amsterdam Tom

1 Berlin Jim

2 Paris Jim

3 Amsterdam Claus

4 Antwerp Claus

5 Barcelona Claus

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值