@valerchik433

Как условно (значение в столбце) искать подстроки в другом столбце в цикле python?

Мне нужно выполнить поиск подстроки в строке по условию во втором столбце. У меня есть 2 фрейма данных:
df1 = {'Descr': ["VALVE, PRESSURE", "pump ttf", "Valve, electrical", "Geeku, electrical","VALVE, OVERBOARD, BUTTERFLY"],
        'N_Product': ["VALVE", "PUMP", "VALVE", "GEEKU","VALVE"],
        }
df2 = {'N_Product': ["VALVE", "VALVE","VALVE", "PUMP", "GEEKU"],
        'M_Product': ["PRESSURE", "qwerty","", "", "ELECTRICAL"],
        }
df1 = pd.DataFrame(df1)
df2 = pd.DataFrame(df2)

  • (шаг 1) Для первой строки в df1 столбец N_Product имеет значение VALVE.

  • (шаг 2) Ищем VALVE в столбце N_Product каждой строки df2 и находим 3 совпадения с следующими парами (N_Product, M_Product): строка 0 содержит VALVE,PRESSURE; строка 1 имеет VALVE, qwerty; строка2 имеет VALVE,"".

  • (шаг 3) Затем вам нужно проверить, содержится ли любая из этих пар (df2(M_Product)) в Df1 ['Descr'], если она содержится, то вам нужно написать N_Product+":"+M_Product+";" . Для Valve нужно искать только "PRESSURE", "Electrical" и "", другие не нужны, для N_Product ('GEEKU') - только "Electrical"' и т.д., в зависимости от того, какие пары есть в файле df2


c = df2['M_Product'].astype(str).to_list()
def matcher(x):
    for i in c:
        if i.lower() in x.lower():
            return i
    else:
        return np.nan
df1['Res'] = df1['Descr'].apply(matcher)

но я не знаю, как перебирать значение только соответствующего M_Product для N_Product.

Желаемый результат:
df1 = {'Descr': ["VALVE, PRESSURE", "pump ttf", "Valve, electrical", "Geeku, electrical","VALVE, OVERBOARD, BUTTERFLY"],
        'N_Product': ["VALVE", "PUMP", "VALVE", "GEEKU","VALVE"],
        },
'Result': ["VALVE: PRESSURE;", "PUMP", "VALVE;", "GEEKU: ELECTRICAL;","VALVE;"],
        }

Буду признателен за любую помощь. Если есть варианты, помогите
  • Вопрос задан
  • 95 просмотров
Решения вопроса 1
phaggi
@phaggi Куратор тега Python
лужу, паяю, ЭВМы починяю
Я тут накропал
велосипедик на костылях
import pandas as pd


def get_pairs(keys: list, data: list) -> dict:
    """
    Подготовительная функция
    Раскладывает значения из data по ключам из key в порядке, как в key
    :param keys: ['foo', 'spam', 'foo', ...]
    :param data: [('foo', 'bar'), ('foo', 'baz'), ('spam', 'ham'), ...]
    :return: {'foo': ['bar', 'baz'], 'spam': ['ham'], ...}
    """
    inter_pairs = dict([(key, []) for key in set(keys)])
    while bool(len(data)):
        key, value = data.pop(0)
        inter_pairs[key].append(value)
    return inter_pairs


def prepare_next_attr(key: str, value: str, descr: list) -> tuple:
    """
    Служебная функция
    Готовит очередной комплект атрибутов
    для вычисления следующего результата
    :param key:
    :param value:
    :param descr:
    :return: next_key, next_pair, next_descr
    """
    descr = [i.lower() for i in descr]
    next_key = f'{key.lower()}, '
    next_pair = f'{next_key}{value.lower()}'
    next_descr = descr.pop(0)
    return next_key, next_pair, next_descr


def get_next_res_item(key: str, value: str, descr: list) -> str:
    """
    Служебная функция
    Готовит результат, сравнивая по Descr
    (тут подгонка if-ами под задание)
    :param key:
    :param value:
    :param descr:
    :return: результат для помещения в список результатов
    """
    next_key, next_pair, next_descr = prepare_next_attr(key, value, descr)
    if next_pair == next_descr:
        res_item = f'{key}: {value};'
    elif next_key in next_descr:
        res_item = f'{key};'
    else:
        res_item = f'{key}'
    return res_item


def make_result(keys: list, inter_pairs: dict, descr: list) -> pd.Series:
    """
    Перебирает ключи, получает для каждого очередной результат,
    складывает результаты в pd.Series
    :param keys:
    :param inter_pairs:
    :param descr:
    :return: pd.Series с результатами
    """
    intermedia_result = []
    for key in keys:
        value = inter_pairs[key].pop(0)
        intermedia_result.append(
            get_next_res_item(key,
                              value,
                              descr)
        )
    return pd.Series(intermedia_result)


if __name__ == '__main__':
    df1 = {
        'Descr': ["VALVE, PRESSURE", "pump ttf", "Valve, electrical", "Geeku, electrical",
                  "VALVE, OVERBOARD, BUTTERFLY"],
        'N_Product': ["VALVE", "PUMP", "VALVE", "GEEKU", "VALVE"],
    }
    df2 = {'N_Product': ["VALVE", "VALVE", "VALVE", "PUMP", "GEEKU"],
           'M_Product': ["PRESSURE", "qwerty", "", "", "ELECTRICAL"],
           }
    target = {
        'Descr': ["VALVE, PRESSURE", "pump ttf", "Valve, electrical", "Geeku, electrical", "VALVE, OVERBOARD, "
                                                                                           "BUTTERFLY"],
        'N_Product': ["VALVE", "PUMP", "VALVE", "GEEKU", "VALVE"],
        'Result': ["VALVE: PRESSURE;", "PUMP", "VALVE;", "GEEKU: ELECTRICAL;", "VALVE;"], }
    df1 = pd.DataFrame(df1)
    df2 = pd.DataFrame(df2)
    df_target = pd.DataFrame(target)

    df2_list = list(zip(df2['N_Product'], df2['M_Product']))
    pairs = get_pairs(df1['N_Product'], df2_list)
    result = make_result(df1['N_Product'], pairs, df1['Descr'])
    df1['Result'] = result.values

    print(df1)
    print(all(df1 == df_target))

Он вроде формально решает задачу... но опять же формально это не ответ на вопрос, а подгонка под целевое задание, причем совсем не pandas-way. Ну, чем могу...
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы