Я пытаюсь выполнить некоторый рудиментарный анализ воронки с помощью блока данных pandas. Смысл, у меня есть dataframe, содержащий пользователя sessions
, который состоит из серии events
. Я хотел бы иметь возможность группировать по session
, определить, какие sessions
содержат заданный event ordering
(eventA, за которым следует eventB), а затем группировать по date
и получать их с течением времени.анализ воронки с пандами (большой набор данных)
, например, учитывая мой dataframe:
sessions = ['a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'd', 'd', 'd']
events = ['dog', 'cat', 'tree', 'tree', 'dog', 'frog', 'cat', 'dog', 'cat', 'tree', 'cat', 'dog']
d1 = datetime(2014,8,1)
d2 = datetime(2014,8,2)
d3 = datetime(2014,8,3)
dates = [d1, d1, d1, d1, d1, d1, d1, d2, d2, d1, d1, d1]
dic = {'sessions':sessions, 'events':events, 'dates':dates}
df_tot = pd.DataFrame(dic)
производства:
sessionDate events sessions
0 2014-08-01 dog a
1 2014-08-01 cat a
2 2014-08-01 tree a
3 2014-08-01 tree b
4 2014-08-01 dog b
5 2014-08-01 frog b
6 2014-08-01 cat b
7 2014-08-02 dog c
8 2014-08-02 cat c
9 2014-08-01 tree d
10 2014-08-01 cat d
11 2014-08-01 dog d
Я хотел бы получить следующий за заказ событие dog
затем cat
:
reachedFirstEvent reachedSecondEvent total
2014-08-01 1 2 3
2014-08-02 0 1 1
Мой второй проблема в том, что у меня 3 миллиона строк в моем фактическом фрейме. Поэтому я создал взломанное решение. Он работает, но довольно медленный. Любые мысли о том, как это сделать или ускорить мой код?
def find_funnels_ex(dlist,event_list):
m = -1
for i in range(0,len(event_list)):
j = np.where(dlist == event_list[i])[0] #get all indices where cat
j = j[j>=m] #select only indices greater than min dog index
if j.size == 0:
return i
else:
m = np.min(j)
return i+1
sessions = ['a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'd', 'd', 'd']
events = ['dog', 'cat', 'tree', 'tree', 'dog', 'frog', 'cat', 'dog', 'cat', 'tree', 'cat', 'dog']
d1 = datetime(2014,8,1)
d2 = datetime(2014,8,2)
d3 = datetime(2014,8,3)
dates = [d1, d1, d1, d1, d1, d1, d1, d2, d2, d1, d1, d1]
dic = {'sessions':sessions, 'events':events, 'dates':dates}
df_tot = pd.DataFrame(dic)
#get only groups that have at least first event
gb_tot = df_tot.groupby('sessions')
df_filt = gb_tot.filter(lambda x: 'dog' in x['events'].values) #changes to dataframe
#get funnel position for each session
#returns a 1 if first event is reached, returns a 2 if second event is reached, etc
gb_filt = df_filt.groupby('sessions')
gb_funn = gb_filt.aggregate(lambda x: find_funnels_ex(
x['events'].values,
['dog','cat']
)
)
#join this to funnel to get date events funnel was started
gb_filt = gb_filt.aggregate({'dates':np.min})
gb_filt['funnel'] = gb_funn['events']
df_funn = gb_filt.reset_index() #change back to dataframe
#pivot to get columns of funnel position indicators
df_piv = pd.pivot_table(df_funn,'funnel', cols='funnel', rows=['sessions','dates'], aggfunc=np.sum) #pivot
df_piv = df_piv.reset_index() #reset
#group by date and sum
df_piv = df_piv.set_index('dates') #set index
gb_piv = df_piv.groupby(lambda x: x) #groupby date
gb_final = gb_piv.aggregate({1:np.sum,2:np.sum})
#get totals
gb_tot = df_tot.groupby('sessions')
gb_tot = gb_tot.aggregate({'dates':np.min})
gb_tot = gb_tot.set_index('dates') #set index
gb_tot = gb_tot.groupby(lambda x: x).size() #groupby date
gb_final['total'] = gb_tot
gb_final[2] = gb_final.apply(lambda x: x[2]/2.0,axis=1)
Можете ли вы добавить немного подробностей в свой пример о том, почему 'reachFirstEv ent' является '0' для' 2014-08-02'? Если критерии, чтобы достичь первого, даже «собака» в сеансе, то не разрешается ли сессия 'c'? – cwharland
Правильно, так что это происходит из моей функции find_funnels_ex(). Если и только если достигнута вторая часть воронки, она возвращает 2. Если только первая часть достигнута, она возвращает 1. Итак, вы правы, фактический счет firstEventReached должен быть столбцами 1 + 2 – user3439329
Звучит неплохо , работая над записью чего-то, что может помочь. Чтобы лучше понять, ваша цель состоит в том, чтобы сделать две вещи: 1) определить сеансы, которые достигают первого и/или второго события, и 2) для каждой даты суммировать количество сеансов, которые соответствуют этим логическим точкам? Кроме того, массив даты, который у вас есть, не создает список df. он должен читать '[d1, d1, d1, d1, d1, d1, d1, d2, d2, d1, d1, d1]' – cwharland