Денормализация DataFrame названий компаний [Часть 1] - PullRequest
2 голосов
/ 07 июля 2019

У меня есть Pandas DataFrame с названиями компаний, который имеет следующую структуру:

import numpy as np
import pandas as pd

df = pd.DataFrame({'name' : ['Nitron', 'Pulset', 'Rotaxi'], 
                   'postal_code' : [1410, 1020, 1310], 
                   'previous_name1' : ['Rotory', np.NaN, 'Datec'],
                   'previous_name2' : [ np.NaN, 'Cmotor', np.NaN],
                   'previous_name3' : ['Datec', np.NaN, np.NaN]
                  })

print(df)

| name   | postal_code | previous_name1 | previous_name2 | previous_name3 |
|--------|-------------|----------------|----------------|----------------|
| Nitron | 1410        | Rotory         | NaN            | Datec          |
| Pulset | 1020        | NaN            | Cmotor         | NaN            |
| Rotaxi | 1310        | Cyclip         | NaN            | NaN            |

Как вы заметите, компания может иметь до трех предыдущих названий.

Моя цель состоит в том, чтобы «денормализовать» вышеприведенную таблицу, чтобы новый DataFrame имел следующую форму:

| name   | postal_code |
|--------|-------------|
| Nitron | 1410        |
| Rotory | 1410        |
| Datec  | 1410        |
| Pulset | 1020        |
| Cmotor | 1020        |
| Rotaxi | 1310        |
| Cyclip | 1310        |

То есть я хочу добавить новую строку для всех случаев, когда предыдущие названия компаний не пропущены, и впоследствии удалить предыдущие серии имен (я также хочу добавить значение postal_code для каждой новой строки).

Я ищу описание метода (желательно с кодом или псевдокодом), который позволит мне достичь вышеуказанного результата.

1 Ответ

3 голосов
/ 07 июля 2019

Используйте DataFrame.set_index с DataFrame.stack для удаления ошибочных значений и изменения формы, затем удалите второй уровень MultiIndex на DataFrame.reset_index и последнийпреобразовать Series в 2 столбца DataFrame:

df1 = (df.set_index('postal_code')
         .stack()
         .reset_index(level=1, drop=True)
         .reset_index(name='name'))
print (df1)
   postal_code    name
0         1410  Nitron
1         1410  Rotory
2         1410   Datec
3         1020  Pulset
4         1020  Cmotor
5         1310  Rotaxi
6         1310   Datec

Или использовать DataFrame.melt с DataFrame.dropna, но порядок значений отличается:

df1 = (df.melt('postal_code', value_name='name')
         .drop('variable', axis=1)
         .dropna(subset=['name'])
         .reset_index( drop=True)
)
print (df1)
   postal_code    name
0         1410  Nitron
1         1020  Pulset
2         1310  Rotaxi
3         1410  Rotory
4         1310   Datec
5         1020  Cmotor
6         1410   Datec

Но возможна сортировка по первому столбцу:

df1 = (df.melt('postal_code', value_name='name')
         .drop('variable', axis=1)
         .dropna(subset=['name'])
         .sort_values('postal_code')
         .reset_index( drop=True)

)
print (df1)
   postal_code    name
0         1020  Pulset
1         1020  Cmotor
2         1310  Rotaxi
3         1310   Datec
4         1410  Nitron
5         1410  Rotory
6         1410   Datec
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...