如何在单个列上使用 groupby 并对 Pandas 中的多个列进行比较?

Posted

技术标签:

【中文标题】如何在单个列上使用 groupby 并对 Pandas 中的多个列进行比较?【英文标题】:How to use groupby on a single column and perform comparisons for multiple columns in Pandas? 【发布时间】:2019-05-11 15:51:41 【问题描述】:

我有一个用户数据框,无论他们是否已注册,以及模型对他们是否已注册的预测。我想找到每个用户:TP(他们注册并且模型预测他们会这样做)、FP(他们没有注册但模型预测他们会这样做)、FN(他们注册但模型预测不会)和TN(他们没有注册,模型预测没有)。这里 1 表示他们注册,0 表示他们没有。我想对用户进行分组,然后使用其他两列进行比较。例如,我可能有如下内容:

Users    |    Signed_up    |     Prediction   |
User1         1                  0            
User2         0                  0
User1         1                  1
User3         1                  1
User2         0                  1
User2         0                  0
...

For TP, the resulting table might look something like:

Users    |    TP    |
User1         1
User2         0
User3         1

For TN, the resulting table might look something like:
Users    |    TN    |
User1         0
User2         1
User3         0

and so on for FP and FN.

我假设我在 Users 列上分组并使用 lambda 函数来比较 Sign_upPrediction 列,但我不确定如何实际执行此操作。我将不胜感激!

【问题讨论】:

【参考方案1】:

groupbygroupby + sum 之前进行比较

(df.assign(TP = df.Signed_up & df.Prediction, 
           TN = (df.Signed_up == 0) & (df.Prediction == 0),
           FN = df.Signed_up & (df.Prediction == 0), 
           FP = (df.Signed_up == 0) & df.Prediction)
   .groupby('Users')['TP', 'TN', 'FN', 'FP'].sum())

       TP   TN   FN   FP
Users                   
User1   1  0.0  1.0  0.0
User2   0  2.0  0.0  1.0
User3   1  0.0  0.0  0.0

受@BrianJoseph 的启发,您可以通过groupby 全部3 列,确定大小,然后将除用户之外的所有内容拆开:

df.groupby([*df]).size().unstack([1,2]).fillna(0)

Signed_up     1         0     
Prediction    0    1    0    1
Users                         
User1       1.0  1.0  0.0  0.0
User2       0.0  0.0  2.0  1.0
User3       0.0  1.0  0.0  0.0

【讨论】:

为了完整起见,您应该继续添加FN = (df.Signed_up == 1) & (df.Prediction == 1), FP = (df.Signed_up == 0) & (df.Prediction == 1)),这样您就可以处理 FP 和 FN。不过为此点赞!【参考方案2】:

请记住,pandas 可以使用函数结果进行分组。为了区分这 4 类结果,您只需要知道Signed_upPrediction 之间的关系。你可以这样分类:

grps = df.groupby(lambda index: (df.loc[index, 'Signed_up'], df.loc[index, 'Prediction']))

这只是为您提供 groupby 对象,您可以随意命名组,例如:

tp_df = grps.get_group((1,1))

【讨论】:

【参考方案3】:

如果创建不同的 dfs,对于您帖子中看起来像是的每个模型预测,您可以使用布尔掩码和 & 位运算符来执行此操作。 & 表示必须同时满足两个条件才能返回值,所以:

df = pd.read_csv('./Desktop/models.csv')

TP = df.loc[(df['Signed_up'] == 1) & (df['Prediction'] == 1)]

TN = df.loc[(df['Signed_up'] == 0) & (df['Prediction'] == 0)]

FN = df.loc[(df['Signed_up'] == 1) & (df['Prediction'] == 0)]

FP = df.loc[(df['Signed_up'] == 0) & (df['Prediction'] == 1)]

输出:

>>> TP
   Users  Signed_up  Prediction
2  User1          1           1
3  User3          1           1
>>> TN = df.loc[(df['Signed_up'] == 0) & (df['Prediction'] == 0)]
>>> TN
   Users  Signed_up  Prediction
1  User2          0           0
5  User2          0           0
>>> FN = df.loc[(df['Signed_up'] == 1) & (df['Prediction'] == 0)]
>>> FN
   Users  Signed_up  Prediction
0  User1          1           0
>>> FP = df.loc[(df['Signed_up'] == 0) & (df['Prediction'] == 1)]
>>> FP
   Users  Signed_up  Prediction
4  User2          0           1

【讨论】:

以上是关于如何在单个列上使用 groupby 并对 Pandas 中的多个列进行比较?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LINQ to SQL 在计算列上获得不同的值?

从 Spark DataSet 中的单个列派生多个列并在新列上分组 [重复]

如何在大量数据框列上应用我的 single_space 函数? [关闭]

根据列上的条件获取记录的单个值

postgresql中多个列上的多个索引与单个索引

熊猫重新采样时间序列数据 - 同一列上有多个 agg 函数?