ВПР с помощью Python
Есть два датасета. В df_spec
- компоненты, их аналоги и их количество на одно устройство. В df_all_comp
- компоненты каждого вида с количеством на складе.
Необходимо в таблицу df_spec
добавить количества каждого компонента и его аналога из таблицы df_all_comp
(заполнить ими столбцы Quantity_Comp, Quantity_A1, Quantity_A2
)
Мой код:
df_spec = pd.DataFrame({'Comp': ['s1', 'c1', 'p1', 'l1', 't1', 'r1', 'a1', 'm1'],
'analog1': ['s2', 'c2', 'p2', 'l2', 't2', None, 'a2', 'm2'],
'analog2': ['s3', 'c3', None, None, 't3', None, None, 'm3'],
'Quantity_per_1': [4.0, 3.0, 9.0, 0.0, 4.0, 11.0, 25.0, 11]})
df_spec['Quantity_Comp'] = np.nan
df_spec['Quantity_A1'] = np.nan
df_spec['Quantity_A2'] = np.nan
df_all_comp = pd.DataFrame({'Comp': ['s1', 's2', 's3', 'c1', 'c2', 'c3', 'p1', 'p2', 'l1', 'l2', 't1', 't2', 't3', 'r1', 'a1', 'a2', 'm1', 'm2', 'm3'],
'Quantity': [4.0, 3.0, 9.0, 0.0, 4.0, 11.0, 25.0, 11.0, 13.0, 3.0, 4.0, 3.0, 9.0, 0.0, 4.0, 11.0, 25.0, 11.0, 13.0]})
#print(df_all_comp)
df=pd.merge(df_spec, df_all_comp, on='Comp', how='outer') # равно как и left, inner и т.д.
df=pd.merge(df_spec, df_all_comp, on='Quantity_A1', how='outer')
df=pd.merge(df_spec, df_all_comp, on='Quantity_A2', how='outer')
print (df)
Этот код коверкает таблицу, увеличивая количество строк. То есть, на выходе должна быть таблица из 8 строк. Как грамотно спарсить компоненты из одной таблицы в другую?
Ответы (1 шт):
Будем исходить из того, что в df_all_comp
каждое наименование комплектующих встречается ровно один раз.
Преобразуем df_all_comp
в последовательность pandas.Series
, индексы которой - это наименования деталей, а значения - количество деталей на складе:
df_all = df_all_comp.set_index('Comp').squeeze()
У этой последовательности есть метод Series.get, который принимает индекс и возвращает содержимое по нему, если есть что возвращать, или дефолтное значение, по умолчанию равное None
. Этот метод мы передадим как аргумент методу DataFrame.map исходной таблицы, чтобы заменить наименования комплектующих на их количество на складе:
df_comp_count = (
df_spec
.set_index('Comp') # сохраним опорные комплектующие в индексе
.filter(regex=r'^analog[0-9]+$') # выберем столбцы наименований аналогов
.reset_index() # вернем опорные комплектующие в столбцы
.map(df_all.get) # заменим наименование комплектующих на их количество на складе
.rename(columns='Quantity_{}'.format) # добавим к названию столбцов `Quantity`, чтобы не путать с исходными
)
Результат присоединяем к исходной таблице:
df = df_spec.join(df_comp_count) # join по индексам
Полный код в чуть более сжатом виде:
import pandas as pd
df_spec = pd.DataFrame({
'Comp': ['s1', 'c1', 'p1', 'l1', 't1', 'r1', 'a1', 'm1'],
'analog1': ['s2', 'c2', 'p2', 'l2', 't2', None, 'a2', 'm2'],
'analog2': ['s3', 'c3', None, None, 't3', None, None, 'm3'],
'Quantity_per_1': [4.0, 3.0, 9.0, 0.0, 4.0, 11.0, 25.0, 11]
})
df_all_comp = pd.DataFrame({
'Comp': ['s1', 's2', 's3', 'c1', 'c2', 'c3', 'p1', 'p2', 'l1', 'l2', 't1', 't2', 't3', 'r1', 'a1', 'a2', 'm1', 'm2', 'm3'],
'Quantity': [4.0, 3.0, 9.0, 0.0, 4.0, 11.0, 25.0, 11.0, 13.0, 3.0, 4.0, 3.0, 9.0, 0.0, 4.0, 11.0, 25.0, 11.0, 13.0]
})
df = df_spec.join(
df_spec[['Comp', 'analog1', 'analog2']]
.map(df_all_comp.set_index('Comp').squeeze().get)
.rename(columns='Quantity_{}'.format)
)
print(df.to_string())
Результат:
Comp analog1 analog2 Quantity_per_1 Quantity_Comp Quantity_analog1 Quantity_analog2
0 s1 s2 s3 4.0 4.0 3.0 9.0
1 c1 c2 c3 3.0 0.0 4.0 11.0
2 p1 p2 None 9.0 25.0 11.0 NaN
3 l1 l2 None 0.0 13.0 3.0 NaN
4 t1 t2 t3 4.0 4.0 3.0 9.0
5 r1 None None 11.0 0.0 NaN NaN
6 a1 a2 None 25.0 4.0 11.0 NaN
7 m1 m2 m3 11.0 25.0 11.0 13.0