首页 > 解决方案 > 将嵌套数据框转换为简单的数据框

问题描述

真的需要帮助,因为教程似乎没有解决这个问题。我花了一整天的时间,找不到解决方案。

我下载了 API 数据并从 json 转换为 python 字典格式。但是,字典很复杂,它有一个字典的字典。

这是字典的头部:

df[1]
Out[47]: 
flight_date                                             2020-07-07
flight_status                                            scheduled
departure        {'airport': 'Findel', 'timezone': 'Europe/Luxe...
arrival          {'airport': 'Francisco Sá Carneiro', 'timezone...
airline          {'name': 'TAP Air Portugal', 'iata': 'TP', 'ic...
flight           {'number': '6794', 'iata': 'TP6794', 'icao': '...
aircraft                                                      None
live                                                          None
Name: 1, dtype: object

字典的图片

在 Departure 和 Arrival 行中有不同机场的 iata çodes(例如:'iata':'LUX')。请参见下面的示例。

出发字典:

{'airport': 'Findel', 'timezone': 'Europe/Luxembourg', 'iata': 'LUX', 'icao': 'ELLX', 'terminal': None, 'gate': None, 'delay': None, 'scheduled': '2020-07-07T06:30:00+00:00', 'estimated': '2020-07-07T06:30:00+00:00', 'actual': None, 'estimated_runway': None, 'actual_runway': None}

我试图将这些复杂的字典简化为一个简单的表格,该表格由给定日期的出发 iata 代码和相应的到达 iata 代码列组成。

如果您对如何解决它有任何想法或知道好的文档,请发送。

非常感谢!

标签: pythondataframe

解决方案


对于字典中的单个值,您可以使用

df['departure_iata'] = df['departure'].apply(lambda item: item['iata'])

对于少数值,您可以使用类似的Series

df[['departure_airport', 'departure_iata']] = df['departure'].apply(lambda item: pd.Series([item['airport'], item['iata']]))

对于您可以使用的所有值,... = df['departure'].apply(pd.Series)但它需要手动编写所有列的名称

df[['departure_airport', 'departure_timezone', 'departure_iata', 'departure_icao', 'departure_terminal', 'departure_gate', 'departure_delay', 'departure_scheduled', 'departure_estimated', 'departure_actual', 'departure_estimated_runway', 'departure_actual_runway'] ] = df['departure'].apply(pd.Series)

使用assign你可以使它更简单,但它不会departure_为新列添加前缀 - 如果你想对arrival具有相同名称的人做同样的事情,它可能会出现问题。

df = df.assign(**df['departure'].apply(pd.Series))

但你可以在Series

df = df.assign(
    **df['departure'].apply(
        lambda item: pd.Series({'departure_'+key:val for key,val in item.items()})
    )
)

编辑:简单一点add_prefix()

df = df.assign(**df['departure'].apply(lambda item:pd.Series(item).add_prefix('departure_')))

或者

df = df.assign(**df['departure'].apply(pd.Series).add_prefix('departure_'))

最少的工作代码

import pandas as pd

data = {
    'A': [1,2,3],
    'B': [4,5,6],
    'departure': [
        {'airport': 'Findel', 'timezone': 'Europe/Luxembourg', 'iata': 'LUX', 'icao': 'ELLX', 'terminal': None, 'gate': None, 'delay': None, 'scheduled': '2020-07-07T06:30:00+00:00', 'estimated': '2020-07-07T06:30:00+00:00', 'actual': None, 'estimated_runway': None, 'actual_runway': None},
        {'airport': 'Findel', 'timezone': 'Europe/Luxembourg', 'iata': 'LUX', 'icao': 'ELLX', 'terminal': None, 'gate': None, 'delay': None, 'scheduled': '2020-07-07T06:30:00+00:00', 'estimated': '2020-07-07T06:30:00+00:00', 'actual': None, 'estimated_runway': None, 'actual_runway': None},
        {'airport': 'Findel', 'timezone': 'Europe/Luxembourg', 'iata': 'LUX', 'icao': 'ELLX', 'terminal': None, 'gate': None, 'delay': None, 'scheduled': '2020-07-07T06:30:00+00:00', 'estimated': '2020-07-07T06:30:00+00:00', 'actual': None, 'estimated_runway': None, 'actual_runway': None},
    ]
} # columns

df = pd.DataFrame(data)
print(df)

df['departure_iata'] = df['departure'].apply(lambda item: item['iata'])
#df['departure_iata'] = df['departure'].str['iata']
print(df['departure_iata'])

df[['departure_airport', 'departure_iata']] = df['departure'].apply(lambda item: pd.Series([item['airport'], item['iata']]))
print(df[['departure_airport', 'departure_iata']])

df[['departure_airport', 'departure_timezone', 'departure_iata', 'departure_icao', 'departure_terminal', 'departure_gate', 'departure_delay', 'departure_scheduled', 'departure_estimated', 'departure_actual', 'departure_estimated_runway', 'departure_actual_runway'] ] = df['departure'].apply(pd.Series)
print(df[['departure_airport', 'departure_iata', 'departure_timezone']])

#----

df = df.assign(**df['departure'].apply(pd.Series))
print(df)

df = df.assign(
    **df['departure'].apply(
        lambda item: pd.Series({'departure_'+key:val for key,val in item.items()})
    )
)
print(df)

df = df.assign(**df['departure'].apply(lambda item:pd.Series(item).add_prefix('departure_')))
print(df)

df = df.assign(**df['departure'].apply(pd.Series).add_prefix('departure_'))
print(df)

顺便说一句:assign()也可以使用concat()

df = pd.concat([df, df['departure'].apply(pd.Series).add_prefix('departure_')], axis=1)
print(df.columns)

你甚至可以删除列'departure'

df = pd.concat([df.drop(['departure'], axis=1), df['departure'].apply(pd.Series).add_prefix('departure_')], axis=1)
print(df.columns)

编辑:

将行转换为列

df = df.T

在示例中,我必须使用apply(eval)因为我将字典作为字符串并且必须转换为 Python 字典。

text = '''flight_date                                             2020-07-07
flight_status                                            scheduled
departure        {'airport': 'Findel', 'timezone': 'Europe/Luxe...'}
arrival          {'airport': 'Francisco Sá Carneiro', 'timezone':'...'}
airline          {'name': 'TAP Air Portugal', 'iata': 'TP', 'icao':'...'}
flight           {'number': '6794', 'iata': 'TP6794', 'icao': '...'}
aircraft                                                      None
live                                                          None'''

import pandas as pd
import io

df = pd.read_csv(io.StringIO(text), sep='\s{2,}', header=None)

df.rename(columns={0:'index'}, inplace=True)
df.index = df['index']
df = df.drop('index', axis=1)
print(df)
print('---')

df = df.T
print(df)
print('---')

df['departure'] = df['departure'].apply(eval)

df['departure_airport'] = df['departure'].apply(lambda item: item['airport'])

print(df['departure_airport'])

推荐阅读