Применить выполненную на заказ функцию к pandas df - PullRequest
0 голосов
/ 12 февраля 2020

Я определил следующую функцию, которая ищет во вложенных словарях значение определенной клавиши c.

def get_recursively(search_dict, field):

    fields_found = []

    if len(search_dict) == 1:
        search_dict = search_dict[0]

    for key, value in search_dict.items():

        if key == field:
            fields_found.append(value)

        elif isinstance(value, dict):
            results = get_recursively(value, field)
            for result in results:
                fields_found.append(result)

        elif isinstance(value, list):
            for item in value:
                if isinstance(item, dict):
                    more_results = get_recursively(item, field)
                    for another_result in more_results:
                        fields_found.append(another_result)

    return fields_found

Теперь, скажем, я хочу применить эту функцию к столбцу в pandas DF и сохранить результат в новом столбце. Мои данные выглядят так:

id              metadata                    field
123             {"dek": "fashion...}        frontend
124.            {"dek": "house...}          frontend

Я попробовал следующий код:

df['NewCol'] = df.apply(lambda x: get_recursively(x['metadata'], x['field']), axis=1)

Так что в этом случае я передаю столбец metadata и значение столбца field который является «интерфейсом» в качестве аргументов. Я получил ошибку: KeyError: (0, 'occurred at index 2') Когда я тестировал свою функцию на одном вложенном словаре, сохраненном в переменной, он дал мне именно то, что мне было нужно, то есть значение ключевого интерфейса. Что я здесь не так делаю?

Ниже приведен пример вложенных диктов, с которыми я имею дело:

{"dek": "<p>Don\'t forget to buy a card</p>", "links": {"edit": {"dev": "//patty-menshealth.feature.hearstapps.net/en/content/edit/76517422-96ad-4b5c-a24a-c080c58bce0c", "prod": "//patty-menshealth.prod.hearstapps.com/en/content/edit/76517422-96ad-4b5c-a24a-c080c58bce0c", "stage": "//patty-menshealth.stage.hearstapps.net/en/content/edit/76517422-96ad-4b5c-a24a-c080c58bce0c"}, "frontend": {"dev": "//menshealth.feature.hearstapps.net/trending-news/a19521193/fathers-day-weekend-plans/", "prod": "//www.menshealth.com/trending-news/a19521193/fathers-day-weekend-plans/", "stage": "//menshealth.stage.hearstapps.net/trending-news/a19521193/fathers-day-weekend-plans/"}}, "header": {"title_color": 1, "title_layout": 1}, "sponsor": {"program_type": 1, "tracking_urls": []}, "social_dek": "<p>Don\'t forget to buy a card</p>", "auto_social": 0, "index_title": "\u200bWeekend Guide: Treat Your Dad Right This Father\'s Day", "short_title": "Treat Your Dad Right This Father\'s Day", "social_title": "\u200bWeekend Guide: Treat Your Dad Right This Father\'s Day", "editors_notes": "<p>nid: 2801076<br>created_date: 2017-06-16 13:00:01<br>compass_feed_date: 2017-06-21 14:01:58<br>contract_id: 40</p>", "seo_meta_title": "Treat Your Dad Right This Father\'s Day\u200b | Men’s Health", "social_share_url": "/trending-news/a19521193/fathers-day-weekend-plans/", "seo_related_links": {}, "editor_attribution": "by", "hide_from_homepage": 1, "syndication_rights": 3, "seo_meta_description": "\u200bFrom gifts to food ideas, we\'ve got your Father\'s Day covered. Just don\'t forget to buy him a card."}

1 Ответ

1 голос
/ 12 февраля 2020

Кажется, что ключевая ошибка была вызвана первым оператором if:

if len(search_dict) == 1:
    search_dict = search_dict[0]

У меня были проблемы с проверкой типа Dict, и я решил попробовать с collection.Mapping вместо dict. Я протестировал решение ниже, и оно, кажется, работает.

import collections

def get_recursively(search_dict, field):

    fields_found = []
    for key, value in search_dict.items():

        if key == field:
            fields_found.append(value)

        elif isinstance(value, collections.Mapping):
            results = get_recursively(value, field)
            for result in results:
                fields_found.append(result)

        elif isinstance(value, list):
            for item in value:
                if isinstance(item, dict):
                    more_results = get_recursively(item, field)
                    for another_result in more_results:
                        fields_found.append(another_result)

    return fields_found
...