Условная замена в рамках датафрейма - PullRequest
1 голос
/ 11 июня 2019

Я использую довольно большой фрейм данных histdf (20M, 3).Поля Visitor_ID, content и time.Фрейм данных будет использоваться для системы рекомендаций URL, где Visitor_ID - это уникальная идентификация посетителя, контент - это посещенный URL, а время - отметка времени.

С этой структурой для каждого уникального посетителя существует несколько URL., но есть посетители, от которых следует отказаться, потому что они не будут выдавать важную информацию (то есть они посещают слишком мало URL-адресов).

Таким образом, я создал новую переменную с именем user_visits, с количеством строк науникальное значение в histdf.Visitor_ID, а затем я отфильтровал его по числу, превышающему 10:

user_visits = histdf.Visitor_ID.value_counts()
mask_user = user_visits > 10

mask_user - это серия панд.Индексом является Visitor_ID, а значения являются логическими (True, если в исходном кадре данных было более 10 строк с этим Visitor_ID).

Теперь я хочу добавить новый столбец heavyuser в histdf сИстинные или Ложные значения от mask_user.

До сих пор я устанавливал значения в кадре данных с использованием этого кода:

for index in histdf.index:
    temp = histdf.loc[index, 'Visitor_ID']
    temp2 = mask_user[temp]
    histdf.set_value(index, 'heavyuser', temp2)

Это своего рода работа.Это гораздо быстрее, чем использование iterrows или других видов итераций по строкам.Тем не менее, он все еще медленный, с длительностью обработки более 1 часа.

Мне было интересно, есть ли какой-то другой вариант с лучшей производительностью.Сводка будет считывать количество строк на отдельного пользователя Visitor_ID, если эти строки меньше порогового значения (в данном случае 10), либо поместите False в новый столбец данных, либо удалите строки в целом.

Буду признателен за любую подсказку.Спасибо.

1 Ответ

2 голосов
/ 11 июня 2019

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

Вот как вы можете это сделать:

histdf = pd.DataFrame({'Visitor_ID':[1, 1, 2, 2, 2, 3], 
                   'content ': ["url" + str(x) for x in range(6)], 
                   'time':["timestamp n° " + str(x) for x in range(6)]}) 

# At first we consider that no user is a heavy user
histdf['heavy user'] = False

# Then we extract the ID's of heavy users
user_visits = histdf.Visitor_ID.value_counts()
id_heavy_users = user_visits[user_visits > 1].index

# Finally we consider those users as heavy users in the corresponding column
histdf.loc[histdf['Visitor_ID'].isin(id_heavy_users), 'heavy user'] = True

Выход:

  Visitor_ID content             time  heavy user
0           1     url0  timestamp n° 0        True
1           1     url1  timestamp n° 1        True
2           2     url2  timestamp n° 2        True
3           2     url3  timestamp n° 3        True
4           2     url4  timestamp n° 4        True
5           3     url5  timestamp n° 5       False

Если вы просто хотите, чтобы крупные пользователи, о которых вы упоминали в конце своего вопроса, вы можете сделать это без создания третьего столбца, например:

histdf = pd.DataFrame({'Visitor_ID':[1, 1, 2, 2, 2, 3], 
                   'content ': ["url" + str(x) for x in range(6)], 
                   'time':["timestamp n° " + str(x) for x in range(6)]}) 

user_visits = histdf.Visitor_ID.value_counts()
id_heavy_users = user_visits[user_visits > 1].index

heavy_users = histdf[histdf['Visitor_ID'].isin(id_heavy_users)]

In [1] : print(heavy_users)
Out[1] :    Visitor_ID content             time
0           1     url0  timestamp n° 0
1           1     url1  timestamp n° 1
2           2     url2  timestamp n° 2
3           2     url3  timestamp n° 3
4           2     url4  timestamp n° 4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...