Получить уникальные значения из одного столбца данных и использовать его для фильтрации строк в другом кадре - PullRequest
0 голосов
/ 26 октября 2018

Я хочу использовать один столбец в df1 в качестве фильтра для df2:

df1 = [('Client', ['A', 'A', 'A', 'B', 'C', 'D', 'D',]),
                    ('Num_Trades', ['1', '2', '3', '1', '1', '1', '1',])
      ]

df1 = pd.DataFrame.from_items(df1)
display(df1)

    Client  Num_Trades
0   A       1
1   A       2
2   A       3
3   B       1
4   C       1
5   D       1
6   D       1

Теперь извлеките уникальные клиенты из df1:

mask_array = df1.Client.unique()
mask_array = dataframe=pd.DataFrame(mask_array, columns=['Client']) 
# mask_list = df1['Client'].unique().tolist()
# mask_list = dataframe=pd.DataFrame(mask_list, columns=['Client']) 
display(mask_array)

    Client
0   A
1   B
2   C
3   D

Пример кадра данных для фильтрации:

df2 = [('Client', ['A', 'B', 'A', 'Y',]),
('Product', ['GOVT', 'GOVT', 'GOVT', 'GOVT',]),
('currency_str', ['USD', 'GBP', 'USD', 'NZD',]),
('Amount', ['10', '20', '30', '40',]),
         ]
# create pandas df
df2 = pd.DataFrame.from_items(df2)
display(df2)


        Client  Product currency_str    Amount
0       A       GOVT    USD             10
1       B       GOVT    GBP             20
2       A       GOVT    USD             30
3       Y       GOVT    NZD             40

Желаемый результат - это просто все строки, суммированные в сумме, где клиент существует в df1:

Client  Product currency_str    Amount
A       GOVT    USD             40
B       GOVT    GBP             20

Мой код создает объекты 'DataFrame', которые могут изменяться, поэтому их нельзя хэшировать. Я попытался использовать массив и список, а также. Итак, что нужно сделать с уникальным набором записей, чтобы их можно было использовать в качестве фильтра для df2?

d = [ 
        ('Amount', 'sum')     
    ] 

# aggregate 
mask = df2['Client'].str.contains(mask_list) 
df2 = df2[mask].groupby(['Client','Product','currency_str'])['Amount'].agg(d).reset_index()
display(df2)

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Это работает для меня. Я заметил, что сумма на самом деле является строкой, поэтому ее нужно конвертировать в идеале перед групповым. Если вы не можете преобразовать здесь мое решение:

Создать список уникальных клиентов df1:

df1['Client'].unique()

массив (['A', 'B', 'C', 'D'], dtype = объект)

Затем используйте его для фильтрации df2 в столбце Client

df2[
    df2['Client'].isin(df1['Client'].unique())
]

Теперь добавьте groupby и lambda для работы со строковыми суммами:

df2[
    df2['Client'].isin(df1['Client'].unique())
].groupby(['Client','Product','currency_str'])['Amount'].apply(lambda x: sum([np.int(x) for x in x.values]))

Client  Product  currency_str
A       GOVT     USD             40
B       GOVT     GBP             20
Name: Amount, dtype: int64

Примечание:

apply(lambda x: sum([np.int(x) for x in x.values]))

делает следующее. Каждое значение в количестве столбца преобразуется в int через np.int и сохраняется в списке. Затем в этом списке делается сумма. Пример: Для клиента A: сумма '10' и '30' возвращается группой, но вы не можете суммировать строки. Так что конвертируйте индивидуально, а затем примените sum ().

Добавить:

.to_frame('Amount').reset_index()


    Client  Product     currency_str    Amount
0   A       GOVT        USD             40
1   B       GOVT        GBP             20
0 голосов
/ 26 октября 2018

Вы можете использовать join с | для регулярных выражений OR, если необходимо отфильтровать по подстрокам:

mask = df2['Client'].str.contains('|'.join(df1.Client.unique()))

Или использовать isin, если хотите отфильтровать по значениям:

mask = df2['Client'].isin(df1.Client.unique())

df2['Amount'] = df2['Amount'].astype(int)
df2 = df2[mask].groupby(['Client','Product','currency_str'])['Amount'].agg(d).reset_index()
print(df2)
  Client Product currency_str  Amount
0      A    GOVT          USD      40
1      B    GOVT          GBP      20
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...