Pandas столбцов и выберите правильное значение - PullRequest
1 голос
/ 05 мая 2020

У меня есть pandas dataframe, который выглядит так:

Book_Name          Book_Ids            Countries_Published
Book_A             [123]               [USA]
Book_B             [4670,1122]         [Canada, USA]
Book_C             [11,200,7688]       [Japan, USA, Canada]
Book_D             [500,400,600]       [NaN, Japan, Canada]
Book_E             [987]               [Japan]

Идентификаторы книг и страны_публикации имеют 1:1 mapping. Это означает, например, во второй строке 4670 corresponds to Canada и 1122 corresponds to USA. Возможны только три страны, хотя Countries_Published could have NaN’s как показано в приведенном выше фрагменте.

Мой выходной фрейм данных должен быть one to one mapping between the name of the book and one of the Book Ids со следующим правилом:

If the list of Book_Ids has only one ID , pick that. If there are more than one , pick according to the following ranking : USA > Canada > Japan

Итак, выходной DF будет выглядеть так:

Book_Name          Book_ID
Book_A             123      (only one in the list)
Book_B             1122     (maps to USA)
Book_C             200      (maps to USA)
Book_D             600      (maps to Canada)
Book_E             987      (only one in the list)

То, что я пробовал до сих пор: создал столбец dict в исходном DF и написал сложный if then else l oop. Есть ли элегантный способ добиться этого?

Ответы [ 2 ]

1 голос
/ 05 мая 2020

Сначала вы создаете средство отображения названий стран для сортировки, а затем находите нужную страну с помощью заявки.

m = {'USA':0, 'Canada': 1, 'Japan':2}
df['Book_ID'] = (
    df.assign(d = df.Countries_Published.apply(lambda x: np.argmin([m.get(e,3) for e in x])))
    .apply(lambda x: x.Book_Ids[0] if len(x)==1 else x.Book_Ids[x.d], axis=1)
)
1 голос
/ 05 мая 2020

Лучше всего разбить его на последовательные шаги:

import pandas as pd
import numpy as np

columns = ["Book_Name", "Book_Ids", "Countries_Published"]
data = np.array([
['Book_A',             [123],               ['USA']],
['Book_B',             [4670,1122],         ['Canada', 'USA']],
['Book_C',             [11,200,7688],       ['Japan', 'USA', 'Canada']],
['Book_D',             [500,400,600],       ['NaN', 'Japan', 'Canada']],
['Book_E',             [987],               ['Japan']],
])
df = pd.DataFrame(data, columns=columns)

Функция ранжирования элементов по стране

def country_rank(item, ranking=['USA', 'Canada', 'Japan']):
    try:
        i = ranking.index(item[0])
    except ValueError:
        i = len(ranking)
    return i

print(country_rank(('Canada', 999)))  # 1

Функция для объединения стран и идентификаторов, а затем выбора страны с номер наименьшего ранга:

def pick_book_id(x):
    book_ids = list(zip(x['Countries_Published'], x['Book_Ids']))
    return min(book_ids, key=country_rank)

pick_book_id(df.loc[1])  # ('USA', 1122)

Сложите все вместе:

df['Selected IDs'] = df.apply(pick_book_id, axis=1)
print(df)

Вывод:

  Book_Name         Book_Ids   Countries_Published   Selected IDs
0    Book_A            [123]                 [USA]     (USA, 123)
1    Book_B     [4670, 1122]         [Canada, USA]    (USA, 1122)
2    Book_C  [11, 200, 7688]  [Japan, USA, Canada]     (USA, 200)
3    Book_D  [500, 400, 600]  [NaN, Japan, Canada]  (Canada, 600)
4    Book_E            [987]               [Japan]   (Japan, 987)
...