【发布时间】:2014-09-18 02:51:05
【问题描述】:
我正在尝试使用 pandas 数据框进行一些基本的漏斗分析。意思是,我有一个包含用户sessions 的数据框,它由一系列events 组成。我希望能够按session 分组,确定哪些sessions 包含给定的event ordering(事件A 后跟事件B),然后按date 分组,并随着时间的推移获得这些计数。
例如,给定我的数据框:
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
我的第二个问题是,我的实际数据框中有 300 万行。所以我建立了一个黑客在一起的解决方案。它可以工作,但速度很慢。关于如何执行此操作或加快我的代码的任何想法?
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)
【问题讨论】:
-
您能否在您的示例中添加一些细节,说明为什么
reachedFirstEvent是0对于2014-08-02?如果首先达到的标准是会话中的dog,那么会话c不合格吗? -
对,这来自我的 find_funnels_ex() 函数。当且仅当到达漏斗的第二部分时,它才返回 2。否则,如果仅到达第一部分,则返回 1。所以,你是对的,firstEventReached 的实际计数应该是列 1 + 2
-
听起来不错,正在写一些可能有帮助的东西。为了再次更好地理解,您的目标是做两件事:1)识别到达第一个和/或第二个事件的会话,以及 2)对于每个日期,将符合这些布尔值的会话数相加?此外,您拥有的日期数组不会产生您列出的 df 。它需要阅读
[d1,d1,d1,d1,d1,d1,d1,d2,d2,d1,d1,d1] -
非常感谢!我在下面提出了第二个解决方案,但它仍然相当滞后。是的,正如你上面所说,这正是我想要的
-
dog是否必须是会话中的第一个事件才能成为reachedFirst,或者如果狗在会话中的任何位置,它具有reachedFirst?