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。它还没有解决,你的解决方案似乎是针对孤立的行。我喜欢你的虚拟示例,并用它的扩展版本更新了我的问题。你可以运行代码,看看结果是否不同。看看它现在是否更有意义。酷!似乎可以了!谢谢!