Вызов значений из dict для создания логического столбца в фрейме данных

#python-3.x #pandas

Вопрос:

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

 Cost_ranges = {'Metals': ["Cu", "Pb", "Zn", "Ni", "Mo", "Co", "Sn", "U3O8", "Ag", "Au", "Pt", "Pd", "Rh", "Os", "Ru", "Ir"],
               'Cost Maximum': [350, 200, 200, 500, 800, 1000, 250, 2500, 30, 2500, 500, 1000, 6000, 2500, 2500, 2500]}
 

Диктант используется для заполнения приведенной ниже формулы:

 df_Cost['Total Cost'] >= Cost_ranges['Cost Maximum']
 

т. е. df_Cost[«Металл»] содержит значение «Cu», он вызывает «Максимальную стоимость» 350 из dict и использует это для логического выражения, следовательно, формула будет гласить:

 df_Cost[Total Cost] >= 350
 

Мне нужно, чтобы это применялось ко всем строкам в фрейме данных. Я использую df.eval (), но мне нужен дополнительный уровень обработки, чтобы соответствовать правильному пределу на металл.

Я пробовал использовать df.eval(), df.query(), df.loc и df.apply (), но продолжаю получать «Ошибку типа:» Объекты серии изменчивы, поэтому их нельзя хэшировать » или » Ошибка значения: («Длины должны совпадать для сравнения’, (9999,), (16,))’ для каждого решения.

С нетерпением ждем ответов.

Ответ №1:

В зависимости от ваших фактических данных вы можете сделать что-то вроде:

 import numpy as np
import pandas as pd

Cost_ranges = {'Metals': ["Cu", "Pb", "Zn", "Ni", "Mo", "Co", "Sn", "U3O8", "Ag", "Au", "Pt", "Pd", "Rh", "Os", "Ru", "Ir"],
           'Cost Maximum': [350, 200, 200, 500, 800, 1000, 250, 2500, 30, 2500, 500, 1000, 6000, 2500, 2500, 2500]}

N = 20
d = pd.DataFrame({'Metals': np.random.choice(["Cu", "Pb", "Zn", "Ni"], N),
                  'Cost': np.random.random(N) * 1000})

d.merge(pd.DataFrame(Cost_ranges).astype({'Cost Maximum': float}),
        on = "Metals", how = "left")
    .eval('want = Cost > `Cost Maximum`')

#    Metals        Cost  Cost Maximum   want
# 0      Cu  297.386007         350.0  False
# 1      Pb   55.570657         200.0  False
# 2      Pb   91.803336         200.0  False
# 3      Cu  916.273995         350.0   True
# 4      Zn  796.383326         200.0   True
# 5      Pb  112.504581         200.0  False
 

Ответ №2:

Предполагая, что вы df_Cost выглядите немного так (с потенциально большим количеством строк и столбцов):

 >>> df_Cost
   Total Cost Metal
0         315    Cu
1         420    Cu
 

Самый простой способ-использовать словарь для перевода с металла на максимальную стоимость. Затем вам нужно внести Cost_ranges в словарь сопоставление имени металла с ценой:

 >>> cost_lookup = dict(zip(Cost_ranges['Metals'], Cost_ranges['Cost Maximum']))
>>> cost_lookup
{'Cu': 350, 'Pb': 200, 'Zn': 200, 'Ni': 500, 'Mo': 800, 'Co': 1000, 'Sn': 250, 'U3O8': 2500, 'Ag': 30, 'Au': 2500, 'Pt': 500, 'Pd': 1000, 'Rh': 6000, 'Os': 2500, 'Ru': 2500, 'Ir': 2500}
>>> df_Cost['Metal'].map(cost_lookup)
0    350
1    350
Name: Metal, dtype: int64
>>> df_Cost['Total Cost'] >= df_Cost['Metal'].map(cost_lookup)
0    False
1     True
dtype: bool