Python 熊猫-如何根据多个二进制列中的条件按比率分组?
我很好奇,是否有人能用纯熊猫来解决这个问题,而不是像我这样使用循环。当前解决方案按指数级扩展到我分组所依据的参数数量 因此,最初我有一个数据帧,看起来像这样:Python 熊猫-如何根据多个二进制列中的条件按比率分组?,python,pandas,Python,Pandas,我很好奇,是否有人能用纯熊猫来解决这个问题,而不是像我这样使用循环。当前解决方案按指数级扩展到我分组所依据的参数数量 因此,最初我有一个数据帧,看起来像这样: theday device event1 event2 0 2019-02-21 desktop 0 0 1 2019-02-22 desktop 1 1 2 2019-02-23 desktop 0 0 3 2019-0
theday device event1 event2
0 2019-02-21 desktop 0 0
1 2019-02-22 desktop 1 1
2 2019-02-23 desktop 0 0
3 2019-02-24 desktop 1 1
4 2019-02-21 other 0 0
5 2019-02-22 other 1 1
6 2019-02-23 other 0 0
7 2019-02-24 other 1 1
8 2019-02-21 desktop 0 1
9 2019-02-22 desktop 1 0
10 2019-02-23 other 0 1
11 2019-02-24 other 1 0
12 2019-02-21 desktop 0 1
13 2019-02-22 desktop 1 0
14 2019-02-23 other 0 1
15 2019-02-24 other 1 0
您可以使用以下代码生成数据帧:
import pandas as pd
import numpy as np
d = {'theday': ['2019-02-21','2019-02-22', '2019-02-23', '2019-02-24','2019-02-21','2019-02-22', '2019-02-23', '2019-02-24', '2019-02-21','2019-02-22', '2019-02-23', '2019-02-24', '2019-02-21','2019-02-22', '2019-02-23', '2019-02-24'], 'device': ['desktop', 'desktop','desktop','desktop', 'other','other','other','other', 'desktop','desktop', 'other','other', 'desktop','desktop', 'other','other' ], 'event1': [0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1], 'event2': [0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0]}
df = pd.DataFrame(data=d)
每行代表一个用户。所以,我想计算每一天和每一台设备,看到事件1和事件2的用户的比率,除以只看到事件1的用户数量。把它放在一个等式中:转换=number\u users\u seen1\u和\u seen2/number\u users\u seen1
查看事件1和事件2意味着用户在event1
列中有一个“1”,在event2
列中有一个“1”。看到事件1意味着用户在event1
列中有一个“1”
我的解决方案功能如下:
def-get_比率(df、e1、e2):
临时列表=[]
对于df['device'].unique()中的设备:#遍历设备
对于df['theday'].unique()中的日期:#迭代天数
当前_df=df[(df['theday']==theday)&(df['device']==device)]
如果len(当前_-df[当前_-df[e1]==1])==0:
换算率=0
其他:
转换=len(当前_-df[(当前_-df[e1]==1)和(当前_-df[e2]==1)])/len(当前_-df[当前_-df[e1]==1])
temp_dict={“theday”:theday,“device”:device,“conversion”:conversion}
临时列表追加(临时目录)
返回pd.数据帧(临时列表)
如果我做了get_比率(df,“event1”,“event2”)
我得到:
conversion device theday
0 0.000000 desktop 2019-02-21
1 0.333333 desktop 2019-02-22
2 0.000000 desktop 2019-02-23
3 1.000000 desktop 2019-02-24
4 0.000000 other 2019-02-21
5 1.000000 other 2019-02-22
6 0.000000 other 2019-02-23
7 0.333333 other 2019-02-24
这种方法有几个问题:
(1) 该函数目前仅支持日期和设备,但如果我想包含更多参数,我需要修改代码
(2) 函数运行时对我分组所依据的参数数量(指数)的伸缩性非常差
(3) 我在熊猫之外执行部分逻辑
那么,我的问题是,我是否可以在没有for循环的情况下实现相同的转换,而只使用pandas特定的函数?如何计算转换有点不清楚,但您可以在这个答案中更改它。我建议使用
apply
功能
步骤1:
创建数据帧
import pandas as pd
import numpy as np
d = {'date': ['2019-02-21','2019-02-22', '2019-02-23', '2019-02-24','2019-02-21','2019-02-22', '2019-02-23', '2019-02-24'], 'device': ['desktop', 'desktop','desktop','desktop', 'other','other','other','other' ],
'event1': [0,1,0,1,0,1,0,1], 'event2': [0,1,0,1,0,1,0,1]}
df = pd.DataFrame(data=d)
步骤2:
按日期和设备分组
df2=df.groupby(['device','date']).sum()
步骤3:
计算换算
df2['outcome']=df2.apply(lambda x: 0 if ((df2['event1']==1).sum())==0
else (0 if x['event1']==0 else x['event2'] / x['event1']), axis=1)
尽管@Tox-answer在我发布的玩具示例中得到了解决,但在更大的数据集中却没有。问题在于,它在检查给定行是否包含这两个事件之前进行分组。以下工作:
import pandas as pd
import numpy as np
d = {'theday': ['2019-02-21','2019-02-22', '2019-02-23', '2019-02-24','2019-02-21','2019-02-22', '2019-02-23', '2019-02-24', '2019-02-21','2019-02-22', '2019-02-23', '2019-02-24', '2019-02-21','2019-02-22', '2019-02-23', '2019-02-24'], 'device': ['desktop', 'desktop','desktop','desktop', 'other','other','other','other', 'desktop','desktop', 'other','other', 'desktop','desktop', 'other','other' ], 'event1': [0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1], 'event2': [0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0]}
df = pd.DataFrame(data=d)
df['both'] = ((df["event1"] == 1) & (df["event2"] == 1)).astype('int')
df_grouped = df.groupby(['theday', 'device']).sum().reset_index()
df_grouped['conversion'] = (df_grouped['both'] / df_grouped["event1"])
什么是事件1或事件2?我没有跟随。。。另外,请将原始数据帧编辑为更小的子集,以便我们可以轻松地将其粘贴到IDE中,谢谢,但按照您的计算,转换不可能小于1,然后转换=(user1+user2)/user1或(1+user2/user1)@Frenchy,我不明白您在说什么。但要明确的是,我并没有在这里显示完整的数据框,这些只是为了说明一般问题。@aws_学徒我进一步澄清了,希望能有所帮助。好的……我在谈论你在显示数据框中的结果,按照你的解释,不可能有转换<1感谢@Tox的答案,我觉得这已经接近我想要实现的目标了,但还不完全。如果我运行上面定义的函数来获得转换,我会得到不同的结果。澄清:转换等于事件1中有“1”且事件2中有“1”的用户数除以事件1中只有“1”的用户数。请参见以下行:
conversion=len(current_-df[(current_-df[e1]==1)和(current_-df[e2]==1)]/len(current_-df[current_-df[e1]==1])
另外,为了避免被0除,我指定如果事件1中有“1”的用户数为0,则conversion为0。sum()而不是df2['output'=df2.apply(λx:((x['event1']+x['event2'])/(usersEvent1))如果x['event1']==1和x['event2']==1,否则为0,轴=1)
可以解决这个问题吗?再次感谢@Tox。它还没有解决,你的解决方案似乎是针对孤立的行。我喜欢你的虚拟示例,并用它的扩展版本更新了我的问题。你可以运行代码,看看结果是否不同。看看它现在是否更有意义。酷!似乎可以了!谢谢!