Панды - проверить, находится ли подмножество данных в другом. - PullRequest
0 голосов
/ 12 ноября 2018

У меня есть следующий фрейм данных, который я назову 'names':

date       name    code  
6/1/2018   A       5     
6/1/2018   B       5     
7/1/2018   A       5     
7/1/2018   B       5     

У меня есть следующий df, который мне нужно изменить:

date       name    comment   
5/1/2018   A       'Good'    
6/1/2018   A       'Good'    
6/1/2018   B       'Good'    
6/1/2018   C       'Good'    
7/1/2018   A       'Good'    
7/1/2018   B       'Good'    

Мне нужно изменитькомментарий к «Плохо», если имя отсутствует в кадре данных имен на эту дату

Сейчас у меня есть:

df['comment'] = np.where(~df['name'].isin(names['name']), 'Bad', df['comment'])

Хотя, очевидно, это не так 'не работает, потому что не принимает во внимание имя и дату.

Окончательный вывод:

date       name    comment   
5/1/2018   A       'Bad'     
6/1/2018   A       'Good'    
6/1/2018   B       'Good'    
6/1/2018   C       'Bad'     
7/1/2018   A       'Good'    
7/1/2018   B       'Good'    

Первая строка была изменена, поскольку в кадре имен отсутствует запись A для 5/1.Строка C была изменена, поскольку в именах df нет записи C для 6/1 (точнее, вообще нет записи C).

Примечание. Оба кадра данных (имена и df) больше, чем я показал, как по строкам, так и по столбцам.

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

Вы можете использовать pd.Index.isin, затем pd.Series.where:

idx_cols = ['date', 'name']
mask = df.set_index(idx_cols).index.isin(names.set_index(idx_cols).index)

df['comment'].where(mask, '\'Bad\'', inplace=True)

print(df)

       date name comment
0  5/1/2018    A   'Bad'
1  6/1/2018    A  'Good'
2  6/1/2018    B  'Good'
3  6/1/2018    C   'Bad'
4  7/1/2018    A  'Good'
5  7/1/2018    B  'Good'
0 голосов
/ 12 ноября 2018

Решение Performant с использованием pd.Index.get_indexer:

v = names.set_index(['date', 'name'])
m = v.index.get_indexer(pd.MultiIndex.from_arrays([df.date, df.name])) == -1
df.loc[m, 'comment'] = '\'Bad\''

print(df)
      date name comment
0  5/1/2018    A   'Bad'
1  6/1/2018    A  'Good'
2  6/1/2018    B  'Good'
3  6/1/2018    C   'Bad'
4  7/1/2018    A  'Good'
5  7/1/2018    B  'Good'

В качестве альтернативы, сделайте ВЛЕВОЕ ВНЕ merge, определите пропущенные значения справаDataFrame и используйте его для mask строк:

m = df.merge(names, how='left', on=['date', 'name']).code.isna()
df['comment'] = df['comment'].mask(m, '\'Bad\'')

print(df)
       date name comment
0  5/1/2018    A   'Bad'
1  6/1/2018    A  'Good'
2  6/1/2018    B  'Good'
3  6/1/2018    C   'Bad'
4  7/1/2018    A  'Good'
5  7/1/2018    B  'Good'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...