pandas — преобразование 1 фрейма данных в два фрейма данных с помощью внешнего ключа

#python #pandas #dataframe #merge

#python #pandas #фрейм данных #слияние

Вопрос:

У меня есть Dataframe df следующим образом

 df = pd.DataFrame(
    [['tom', 28, "tesla", "model s" ], 
    ['nick', 30, "ford", "mustang"], 
    ['juli', 56, "tesla", "model s"]] , 
    columns = ['PersonName', 'PersonAge', "Car", "CarModel"]
)
df.head()

    PersonName  PersonAge   Car CarModel
0   tom     28  tesla   model s
1   nick    30  ford    mustang
2   juli    56  tesla   model s
 

Я хотел бы преобразовать его в два фрейма данных следующим образом

 Person=
PersonName PersonAge CarId
tom        28        1 
nick       30        2
juli       56        1

Cars=
id Car    Model
1  Tesla  Model S
2  Ford   Mustang
 

Каков был бы правильный способ сделать это?

Комментарии:

1. Можете ли вы добавить рабочий пример, чтобы у всех нас был один и тот же код для начала?

2. @tdelaney да, я редактирую вопрос с помощью глупого примера.

Ответ №1:

Вы можете назначить столбцы новым фреймам данных для создания Person и Cars .

 >>> df = pd.DataFrame(
...     [['tom', 28, "tesla", "model s" ], 
...     ['nick', 30, "ford", "mustang"], 
...     ['juli', 56, "tesla", "model s"]] , 
...     columns = ['PersonName', 'PersonAge', "Car", "CarModel"]
... )
>>> df
  PersonName  PersonAge    Car CarModel
0        tom         28  tesla  model s
1       nick         30   ford  mustang
2       juli         56  tesla  model s
>>> 
>>> Person = df[["PersonName", "PersonAge"]]
>>> Cars = df[["Car", "CarModel"]]
>>> Person
  PersonName  PersonAge
0        tom         28
1       nick         30
2       juli         56
>>> Cars
     Car CarModel
0  tesla  model s
1   ford  mustang
2  tesla  model s
 

Обратите внимание, что ваш исходный фрейм данных имел индекс, и этот индекс сохраняется при создании новых. Этот индекс можно использовать в качестве вашего внешнего ключа. Фактически, часть индексации часто прозрачна в pandas. Чтобы выбрать автомобиль из имени пользователя, вы могли

 >>> Cars[Person["PersonName"] == "nick"]
    Car CarModel
1  ford  mustang
 

Если вы хотите превратить индекс в его собственный столбец, вы можете это сделать

 >>> Cars["id"] = Cars.index
>>> Person["CarId"] = Person.index
>>> Person
  PersonName  PersonAge  CarId
0        tom         28      0
1       nick         30      1
2       juli         56      2
>>> Cars
     Car CarModel  id
0  tesla  model s   0
1   ford  mustang   1
2  tesla  model s   2
 

Но придерживаться операций с индексом, как правило, удобнее …. если вы не сбросите индекс, вам придется использовать другой столбец

Ответ №2:

Следующее дает вам то, что вы хотите.

Используйте groupby для создания фрейма данных Cars

 CarsDF = pd.DataFrame(df.groupby(['Car','CarModel']).Car.count())
CarsDF.columns=['v']
CarsDF = CarsDF.reset_index().drop('v', axis=1)
CarsDF.index.name='CarId'
CarsDF
 

Затем используйте слияние для добавления carId

 PersonDF = df.merge(CarsDF.reset_index())[['PersonName','PersonAge','CarId']]
 

Ответ №3:

Это должно сработать:

 import pandas as pd

df = pd.DataFrame(
    [['tom', 28, "tesla", "model s" ],
    ['nick', 30, "ford", "mustang"],
    ['juli', 56, "tesla", "model s"]] ,
    columns = ['PersonName', 'PersonAge', "Car", "CarModel"]
)
df['Comb'] = df['Car']   ","   df['CarModel']
car_df = pd.DataFrame({'CarId': range(1, len(df['Comb'].unique()) 1), 'Comb': df['Comb'].unique()})
car_df = car_df.merge(df[['Comb', 'Car', 'CarModel']], on=['Comb']).drop_duplicates(subset=['Comb']).drop(columns=['Comb'])

df = df.merge(car_df, on=['Car', 'CarModel']).drop(columns=['Comb', 'Car', 'CarModel'])
car_df = car_df.set_index('CarId')
print(df)
print()
print(car_df)
 

Вывод:

   PersonName  PersonAge  CarId
0        tom         28      1
1       juli         56      1
2       nick         30      2

         Car CarModel
CarId                
1      tesla  model s
2       ford  mustang