Pandas: как выбрать susbset кадра данных с несколькими условиями - PullRequest
0 голосов
/ 02 июля 2018

У меня есть датафрейм, подобный следующему:

    df = pd.DataFrame({'COND1' : [0,4,4,4,0],
                   'NAME' : ['one', 'one', 'two', 'three', 'three'],
                   'COND2' : ['a', 'b', 'a', 'a','b'],
                   'value': [30, 45, 18, 23, 77]})

Где у нас есть два условия: [0,4] и ['a','b']

    df
        COND1   COND2   NAME    value
  0       0      a       one    30
  1       4      a       one    45
  2       4      b       one    25
  3       4      a       two    18
  4       4      a      three   23
  5       4      b      three   77

Для каждого имени я хочу выбрать подмножество с условием COND1=0 & COND2=a, если у меня есть информация, COND1=4 & COND2=b в противном случае.

результирующий кадр данных будет:

    df
        COND1   COND2   NAME    value
  0       0      a       one    30
  1      NaN    Nan      two    NaN
  2       4      b      three   77

Я пытался сделать следующее:

df[ ((df['COND1'] == 0 ) & (df['COND2'] == 'a') | 
(df['COND1'] == 4 ) & (df['COND2'] == 'b'))]

Ответы [ 3 ]

0 голосов
/ 02 июля 2018

Вот одно расширяемое решение с использованием вспомогательного столбца. Идея состоит в том, чтобы создать порядок отображения в словаре и применить его к комбинации из двух серий. Сортировка и удаление дубликатов.

import numpy as np

df = pd.DataFrame({'COND1' : [0,4,4,4,4,4],
                   'NAME' : ['one', 'one', 'one', 'two', 'three', 'three'],
                   'COND2' : ['a', 'a', 'b', 'a', 'a','b'],
                   'value': [30, 45, 25, 18, 23, 77]})

# define order dictionary and apply to dataframe
order = {(0, 'a'): 0, (4, 'b'): 1}
df['order'] = df.set_index(['COND1', 'COND2']).index.map(order.get)

# if not found in dictionary, convert columns to NaN
df.loc[df['order'].isnull(), ['COND1', 'COND2', 'value']] = np.nan

# sort values, drop duplicates, drop helper column
res = df.sort_values('order').drop_duplicates(subset=['NAME']).drop('order', 1)

print(res)

   COND1   NAME COND2  value
0    0.0    one     a   30.0
5    4.0  three     b   77.0
3    NaN    two   NaN    NaN
0 голосов
/ 18 сентября 2018

Я думаю, что это работает:

def conds_are(x,y):
    return df['COND1'].eq(x) & df['COND2'].eq(y)

def name_in(f):
    return df['NAME'].isin(df.loc[f,'NAME'].unique())

# Find rows matching conditions.
good = conds_are(0,'a')
good |= conds_are(4,'b') & ~name_in(good)

# Did we miss any names?
bad = ~name_in(good)

# Build DataFrame from surviving rows.
df1 = df.loc[good|bad].copy()
df1.loc[bad,df.columns.drop('NAME')] = np.nan

Выход:

   COND1   NAME COND2  value
0    0.0    one     a   30.0
2    NaN    two   NaN    NaN
4    4.0  three     b   77.0

На самом деле вам не нужно определять эти функции, но IMO облегчает чтение кода.

Предостережение: столбец value - это число с плавающей точкой, потому что целые числа не обнуляются в пандах .

0 голосов
/ 02 июля 2018

Попробуйте изменить свой результат, используя drop_duplicates (отбросьте ИМЯ, удовлетворяющее обоим условиям, оставьте только одно) с помощью reindex (Добавить обратно ИМЯ не удовлетворяет ни одному условию)

Newdf=df[ ((df['COND1'] == 0 ) & (df['COND2'] == 'a') | (df['COND1'] == 4 ) & (df['COND2'] == 'b'))]
Newdf.sort_values('COND1').drop_duplicates(['NAME']).set_index('NAME').reindex(df.NAME.unique()).reset_index()
Out[378]: 
    NAME  COND1 COND2  value
0    one    0.0     a   30.0
1    two    NaN   NaN    NaN
2  three    4.0     b   77.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...