#python #pandas #numpy
#питон #pandas #numpy
Вопрос:
У меня есть два фрейма данных: пользователи и устройства. Фрейм данных пользователей представляет собой список всех взаимодействий по идентификатору пользователя и метке времени. Однако, если кто-то использует наше приложение в качестве гостя, его идентификатору пользователя присваивается значение device_id. Если эти гости в конечном итоге становятся участниками, мы сопоставляем их user_id с их device_id в фрейме данных devices.
Итак, у нас есть для пользователей
user_id timestamp
user13123 2019-02-17
user224234 2019-02-17
user32134234 2019-02-17
00029AD9-X5X5-999N-807F-73F0EAE4A98B 2019-02-17
Где последняя строка — это гостевой пользователь, с идентификатором устройства, сохраненным как user_id
Затем для устройств
device_id user_id
00029AD9-X5X5-999N-807F-73F0EAE4A98B user3423
37029BD9-D5D5-435D-837F-73F0EAE4A98B user34423
...
Что представляет собой простое сопоставление между идентификаторами устройств и известными идентификаторами пользователей
Итак, что я хочу сделать, это проверить, совпадает ли Users.user_id с Devices.device_id , и если да, установите Users.user_id в Devices.user_id . По сути, я хочу обновить все старые гостевые взаимодействия, чтобы использовать user_id, если у нас есть эта информация в Устройствах.
Некоторое время возился с этим, и это становилось все более и более запутанным, и кажется, что это можно было бы решить довольно чисто в pandas. Любая помощь будет очень признательна.
Спасибо!
Комментарии:
1.
users.user_id.replace(devices.set_index('device_id')['user_id'])
?? илиusers.user_id.map(devices.set_index('device_id')['user_id']).fillna(users.user_id)
??
Ответ №1:
Фреймы данных
In [32]: users
Out[32]:
user_id timestamp
0 user13123 2019-02-17
1 user224234 2019-02-17
2 user32134234 2019-02-17
3 00029AD9-D5D5-435D-807F-73F0EAE4A98B 2019-02-17
In []: devices
Out[]:
device_id user_id
0 00029AD9-D5D5-435D-807F-73F0EAE4A98B user3423
1 37029BD9-D5D5-435D-837F-73F0EAE4A98B user34423
Вычислить фильтр
Все пользователи, для которых user_id
соответствует device_id
In []: filtr = users.user_id.isin(devices.device_id)
In []: filtr
Out[]:
0 False
1 False
2 False
3 True
Name: user_id, dtype: bool
Замените значения
Все отфильтрованные пользователи user_id
заменяются соответствующими user_id
правами устройства users
в фрейме данных.
In []: users.loc[filtr, "user_id"] = users[filtr].user_id.map(devices.set_index("device_id").user_id)
In []: users
Out[]:
user_id timestamp
0 user13123 2019-02-17
1 user224234 2019-02-17
2 user32134234 2019-02-17
3 user3423 2019-02-17
Использование np.where
Просто еще один вариант.
users.loc[:, 'user_id'] = pd.np.where(users.user_id.isin(devices.device_id),
users.user_id.map(devices.set_index('device_id').user_id),
users.user_id)
Эти решения ожидают, что user_id
для каждого существует только один device_id
.
Ответ №2:
левое слияние users
с devices
, fillna
в столбце с левым соединением user_id
(это имя as user_id_y
). Наконец, назначьте это обратно столбцу users.user_id
In [59]: users['user_id'] = users.merge(devices, how='left', left_on='user_id', right_on='device_id')['user_id_y'].fillna(users.user_id)
In [60]: users
Out[60]:
timestamp user_id
0 2019-02-17 user13123
1 2019-02-17 user224234
2 2019-02-17 user32134234
3 2019-02-17 user3423
Ответ №3:
Это цикл, который будет выполняться, хотя все записи, проверяющие идентификатор пользователя, соответствуют идентификатору устройства, и если это так, он обновит фрейм данных пользователя с правильным идентификатором.
for i in range(len(Users.index)):
for p in range(len(Devices.index)):
if(Users.loc[i,"user_id"] == Devices.loc[p,"device_id"]):
# Fixed part of the code, check old version.
Users.loc[i,"user_id"] = Devices.loc[p,"user_id"]
Ответ №4:
Это решение находит список совпадающих идентификаторов, затем перебирает один раз и обновляет идентификаторы пользователя, используя его в качестве индекса.
devices = pd.DataFrame({'device_id':{0:'00029AD9-X5X5-999N-807F-73F0EAE4A98B',1:'37029BD9-D5D5-435D-837F-73F0EAE4A98B'},'user_id':{0:'user3423',1:'user34423'}})
users = pd.DataFrame({'user_id':{0:'user13123',1:'user224234',2:'user32134234',3:'00029AD9-X5X5-999N-807F-73F0EAE4A98B'},'timestamp':{0:'2019-02-17',1:'2019-02-17',2:'2019-02-17',3:'2019-02-17'}})
matching_ids = list(set(users.user_id).intersection(set(devices.device_id)))
for id in matching_ids:
users.loc[users.user_id == id, 'user_id'] = devices.set_index('device_id').at[id, 'user_id']