【问题标题】:Calculating a probability based on several variables in a Pandas dataframe根据 Pandas 数据框中的几个变量计算概率
【发布时间】:2017-05-22 18:20:51
【问题描述】:

我对 Python 和 Pandas 还是很陌生,所以请耐心等待......

我有一个沉船乘客数据框。我已按男性和女性以及按班级将其分解为其他数据框,以创建生存概率。我做了一个函数,将一个数据帧与一个只有幸存者的数据帧进行比较,并计算该组的生存概率:

def survivability(total_pass_df, column, value):
    survivors = sum(did_survive[column] == value)
    total = len(total_pass_df)
    survival_prob = round((survivors / total), 2)
    return survival_prob

但现在我试图比较较小群体的生存能力——例如男性头等舱乘客与女性三等舱乘客。我确实为这两个组制作了数据框,但我仍然无法使用我的生存功能,因为我正在比较两个不同的列 - 性别和类别 - 而不仅仅是一个。

我确切地知道如何使用 Python 执行此操作 - 循环遍历数据框中的“幸存”列(1 或 0),如果它等于 1,则将 1 添加到索引值,然后一旦所有数据都经过,将索引值除以数据帧的长度即可得到生存概率......

但我应该为此使用 Pandas,而我这辈子都无法在脑海中弄清楚该怎么做......

:/

【问题讨论】:

    标签: python loops pandas dataframe


    【解决方案1】:

    如果没有您正在使用的数据框样本,我无法确定我是否正确理解了您的问题。但是根据您对纯 Python 程序的描述,

    我确切地知道如何使用 Python 执行此操作 - 循环遍历数据框中的“幸存”列(1 或 0),如果它等于 1,则将 1 添加到索引值,然后一旦所有数据都经过,将索引值除以数据帧的长度即可得到生存概率......

    你可以在 Pandas 中通过简单的编写来做到这一点

    dataframe['survived'].mean()
    

    就是这样。假设所有值都是 1 或 0,平均值将是 1 的数量除以总行数。

    如果您从包含 survivedsexclass 等列的数据框开始,您可以将其与 Pandas 的布尔索引巧妙地结合起来,以挑选出不同组的存活率.让我以Socialcops Titanic passengers data set 为例进行演示。假设DataFrame被称为df,如果你只想分析男性乘客,你可以得到这些记录为

    df[df['sex'] == 'male']
    

    然后你可以取 thatsurvived 列并得到平均值。

    >>> df[df['sex'] == 'male']['survived'].mean()
    0.19198457888493475
    

    因此,19% 的男性乘客幸存下来。如果要缩小到男性二等舱乘客,则需要使用& 组合条件,如下所示:

    >>> df[(df['sex'] == 'male') & (df['pclass'] == 2)]['survived'].mean()
    0.14619883040935672
    

    这有点笨拙,但有一种更简单的方法实际上可以让您同时处理多个类别。 (问题是这是一种更高级的 Pandas 技术,可能需要一段时间才能理解。)使用DataFrame.groupby() 方法,您可以告诉 Pandas 根据它们在某些列中的值对数据框的行进行分组.例如,

    df.groupby('sex')
    

    告诉 Pandas 按性别对行进行分组:所有男性乘客的记录在一个组中,所有女性乘客的记录在另一个组中。你从groupby() 得到的东西不是DataFrame,它是一种特殊的对象,可以让你应用聚合函数——也就是说,把整个组变成一个数字(或其他东西)的函数。所以,例如,如果你这样做

    >>> df.groupby('sex').mean()
              pclass  survived        age     sibsp     parch       fare  \
    sex                                                                    
    female  2.154506  0.727468  28.687071  0.652361  0.633047  46.198097   
    male    2.372479  0.190985  30.585233  0.413998  0.247924  26.154601   
    
                 body  
    sex                
    female  166.62500  
    male    160.39823  
    

    您会看到,对于每一列,Pandas 对所有该列值的男性乘客记录以及所有女性乘客记录取平均值。你在这里只关心存活率,所以只需使用

    >>> df.groupby('sex').mean()['survived']
    sex
    female    0.727468
    male      0.190985
    

    这样做的一大优势是,如果您想查看小组,您可以将多个列作为分组依据。例如,性别和阶级:

    >>> df.groupby(['sex', 'pclass']).mean()['survived']
    sex     pclass
    female  1         0.965278
            2         0.886792
            3         0.490741
    male    1         0.340782
            2         0.146199
            3         0.152130
    

    (如果您提供多个列名,则必须给 groupby 列名列表)

    【讨论】:

    • 哇哦....我什至没想过只取生存的平均值...我试图找到一种在这个问题中使用 groupby() 的方法,但我仍然发现这有点令人困惑。
    • 这很混乱,别担心 ;-)
    【解决方案2】:

    您是否尝试过按乘客 ID 合并两个数据框,然后在 Pandas 中使用任何行小计和 aggfunc=numpy.mean 做一个数据透视表?

    import pandas as pd
    import numpy as np
    
    # Passenger List
    p_list = pd.DataFrame()
    p_list['ID'] = [1,2,3,4,5,6]
    p_list['Class'] = ['1','2','2','1','2','1']
    p_list['Gender'] = ['M','M','F','F','F','F']
    
    # Survivor List
    s_list = pd.DataFrame()
    s_list['ID'] = [1,2,3,4,5,6]
    s_list['Survived'] = [1,0,0,0,1,0]
    
    # Merge the datasets
    merged = pd.merge(p_list,s_list,how='left',on=['ID'])
    
    # Pivot to get sub means
    result = pd.pivot_table(merged,index=['Class','Gender'],values=['Survived'],aggfunc=np.mean,  margins=True)
    
    # Reset the index
    for x in range(result.index.nlevels-1,-1,-1):
        result.reset_index(level=x,inplace=True)
    print result
    
      Class Gender  Survived
    0     1      F  0.000000
    1     1      M  1.000000
    2     2      F  0.500000
    3     2      M  0.000000
    4   All         0.333333
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-15
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多