Удалить строки, соответствующие группам меньше указанного размера - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть DataFrame ответов на 100 questions_id и 50 user_id.Каждая строка представляет отдельный вопрос от конкретного пользователя.Таблица выглядит примерно так:

user_id | question_id | timetaken | answer_1 | answer_2 |
1015    | 1           | 30        | A        | C        |
1015    | 2           | 45        | B        | B        |
1016    | 1           | 15        | A        | A        |
1016    | 2           | 55        | A        | D        |

Я пытаюсь отфильтровать пользователей, которые не прошли тест.Мой мыслительный процесс для этого заключался в подсчете количества вхождений каждого пользователя в таблицу, если user_id 1015 появляется в столбце user_id 100 раз, я знаю, что они выполнили 100 вопросов.К сожалению, я не могу использовать question_id для фильтрации, так как вопросы случайные, чтобы пользователь мог ответить на 5 вопросов, и один из них мог иметь question_id = 100.

Я думал, что это было мое решение , но не смог понять, как считать вхождения user_id.

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Используйте groupby и filter, очень краткие и предназначенные для этой цели.

df1 = df.groupby('user_id').filter(lambda x: len(x) > 100)

Для повышения производительности используйте np.unique и map:

m = dict(zip(*np.unique(df.user_id, return_counts=True)))
df[df['user_id'].map(m) > 100]
0 голосов
/ 18 декабря 2018

Используйте boolean indexing для фильтрации только строк со счетами, больше похожих на 100 раз, transform с size для возврата Series с тем же размером, что и оригинал DataFrame:

df1 = df[df.groupby('user_id')['question_id'].transform('size') > 100]

Производительность : зависит от количества строк и длины групп, поэтому лучший тест в реальных данных:

np.random.seed(123)
N = 1000000
L = list('abcde') 
df = pd.DataFrame({'question_id': np.random.choice(L, N, p=(.75,.0001,.0005,.0005,.2489)),
                   'user_id':np.random.randint(10000,size=N)})
df = df.sort_values(['user_id','question_id']).reset_index(drop=True)

In [176]: %timeit df[df.groupby('user_id')['question_id'].transform('size') > 100]
74.8 ms ± 2.69 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

#coldspeed solutions
In [177]: %timeit df.groupby('user_id').filter(lambda x: len(x) > 100)
1.4 s ± 44.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [178]: %%timeit
     ...: m = dict(zip(*np.unique(df.user_id, return_counts=True)))
     ...: df[df['user_id'].map(m) > 100]
     ...: 
89.2 ms ± 3.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...