Извлечение данных из строк при включении в список - PullRequest
1 голос
/ 28 октября 2019

Я пытаюсь упорядочить географическую информацию, содержащуюся в 4 столбцах Pandas DataFrame, чтобы административные подразделения одного и того же вида постоянно сохранялись в одном и том же столбце.

Я построил 5 списков строк, содержащих информациюо 5 географических уровнях, которые я хотел бы сохранить.

Я пытался заполнить непротиворечивые столбцы, сравнивая оригинальные 4 непоследовательных столбца с моими 5 непротиворечивыми списками, но присутствие значений nan в исходных столбцах также вызывает ошибки вмой код или возвращает слишком много nans в столбцах результата. Ниже приведен пример минимального кода.

import pandas as pd
df = pd.DataFrame (np.array([['nan', 'Rome', 'Civitavecchia'],
                             ['Asti', 'nan', 'Piedmont'],
                             ['Bozen', 'Sudtirol', 'nan']]),
 columns=['a','b','c'])


town = ['Civitavecchia']
province = ['Rome', 'Asti', 'Bozen']
region = ['Piedmont', 'Sudtirol']

#first attempt returns a ValueError: pattern contains no capture groups:
df['a'].str.extractall ('|'.join(town))#

#second attempt:
#this only yields two out of six not-nan results expected

df['geo1'] = np.where(df.a.isin(town), df.a, np.nan)
df['geo1'] = np.where(df.b.isin(town), df.b, np.nan)
df['geo1'] = np.where(df.c.isin(town), df.c, np.nan)

df['geo2'] = np.where(df.a.isin(province), df.a, np.nan)
df['geo2'] = np.where(df.b.isin(province), df.b, np.nan)
df['geo2'] = np.where(df.c.isin(province), df.c, np.nan)

df['geo3'] = np.where(df.a.isin(region), df.a, np.nan)
df['geo3'] = np.where(df.b.isin(region), df.b, np.nan)
df['geo3'] = np.where(df.c.isin(region), df.c, np.nan)


dftarget = pd.DataFrame (np.array([['Civitavecchia', 'Rome', 'nan'],
                             ['nan', 'Asti', 'Piedmont'],
                             ['nan', 'Bozen', 'Sudtirol']]),
 columns=['geo1','geo2','geo3'])

Вывод, к которому я стремлюсь, описан в dftarget

Ответы [ 2 ]

2 голосов
/ 28 октября 2019

IIUC, вы можете сложить данные, отобразить их и развернуть:

# create a common mapping
d = {}
for t in town: d[t] = 'geo1'
for p in province: d[p] = 'geo2'
for r in region: d[r] = 'geo3'    

# stack data for one-go map
a = (df.stack().to_frame(name='data')
         .reset_index(level=1, drop=True)
    )

# return data
a.dropna().pivot(values='data', columns='col')

Вывод:

col           geo1   geo2      geo3
0    Civitavecchia   Rome       NaN
1              NaN   Asti  Piedmont
2              NaN  Bozen  Sudtirol
1 голос
/ 28 октября 2019

Попробуйте этот метод, используя форматирование f-строки. Вам нужна скобка внутри, чтобы определить вашу группу захвата. Без внутреннего парантериза вы получите ошибку, определенную без захвата группы.

df['c'].str.extract(f'({"|".join(town)})')

Вывод:

               0
0  Civitavecchia
1            NaN
2            NaN
...