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

У меня есть фрейм данных с двумя столбцами: один для ID_number и один для week_number.Это может выглядеть следующим образом:

df1 = pd.DataFrame({'ID_number':[13, 13, 14, 14, 14, 15, 15,16], 'week_number':[1, 2, 1, 2, 3, 1, 4, 5]})

#   ID_number   week_number
#0  13  1
#1  13  2
#2  14  1
#3  14  2
#4  14  3
#5  15  1
#6  15  4
#7  16  5

Я хочу выбрать для каждого другого идентификатора те идентификаторы, в которых значение недели равно 2 и 3, а затем сделать метку для данных.Если у идентификатора нет недели 2 и 3, я помечаю его как 1. Иначе, я помечаю его как 0.

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

def check_courier_week(df, field, weeks):
    weeks_not_provided = weeks
    new_df = df
    new_df['label'] = np.zeros(len(df))
    for c in np.unique(df[field]):
        tmp = df[df[field] == c]
        if len(np.unique(tmp.week_number.isin(weeks_not_provided))) == 1 and np.unique(np.unique(tmp.week_number.isin(weeks_not_provided))) == False:
            new_df['label'][df[field] == c] = 1
        else:
            new_df['label'][df[field] == c] = 0
    return new_df

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

Получившийся ярлык должен быть:

#   ID_number   week_number     label
#0  13  1   0.0
#1  13  2   0.0
#2  14  1   0.0
#3  14  2   0.0
#4  14  3   0.0
#5  15  1   1.0
#6  15  4   1.0
#7  16  5   1.0

Спасибо!

Ответы [ 4 ]

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

Хотя это не эффективно, вы можете использовать set операции через set.isdisjoint:

def checker(x):
    return set(x).isdisjoint({2, 3})

df1['flag'] = df1.groupby('ID_number')['week_number'].transform(checker)

print(df1)

   ID_number  week_number  flag
0         13            1     0
1         13            2     0
2         14            1     0
3         14            2     0
4         14            3     0
5         15            1     1
6         15            4     1
7         16            5     1
0 голосов
/ 16 ноября 2018

Чтобы ответить, как вы могли бы использовать groupby: вы можете сгруппировать по ID_number, а затем просто найти метку таким образом, IE:

df1['label'] = np.zeros(len(df))
grouped_table = df1.groupby('ID_number')
groups = list(set(df1['ID_number']))
for group in groups:
    test_list = list(set(grouped_table.getgroup(group)))
    if (2 in test_list) & (3 in test_list):
        df1.loc[df1['ID_number'] == group]['label'] = 0  
    else:
        df1.loc[df1['ID_number'] == group]['label'] = 1
0 голосов
/ 16 ноября 2018

Использование isin и np.where без группировки:

unique = df1.loc[df1['week_number'].isin([2,3]), 'ID_number'].unique()
df['label'] = np.where(df1['ID_number'].isin(unique), 0, 1)

Или:

df['label'] = (~df1['ID_number'].isin(unique)).astype(int)

print(df)
   ID_number  week_number  label
0         13            1      0
1         13            2      0
2         14            1      0
3         14            2      0
4         14            3      0
5         15            1      1
6         15            4      1
7         16            5      1
0 голосов
/ 16 ноября 2018

Использование groupby с transform any

(~(df1['week_number'].isin([2,3])).groupby(df1['ID_number']).transform('any')).astype(int)
Out[39]: 
0    0
1    0
2    0
3    0
4    0
5    1
6    1
7    1
Name: week_number, dtype: int32
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...