【问题标题】:Pandas: Find unique values from columns to calculate probabilitiesPandas:从列中查找唯一值以计算概率
【发布时间】:2021-08-10 23:26:44
【问题描述】:

我有一个 CSV 格式的大型数据集(大约 200,000 行 x 30 列)。我需要使用 pandas 来预处理这些数据。我在下面包含了一个虚拟数据集,以帮助可视化问题。

data = {'Batsman':['Tom', 'Nick', 'Nick', 'Nick', 'Tom', 'Nick', 'Nick', 'Pete', 'Pete'],
            'Outcome':[1, 0, 1, 'Wide', 'Out', 4, 1, 2, 0],
            'Bowler':['Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Ben', 'Ben']
    }
    
    df = pd.DataFrame(data)
    df

目标是有单独的列来显示击球手和投球手的每个结果的概率。以虚拟数据集中的示例为例,Tom 有 50% 的机会出现“1”或“Out”的结果

这是通过以下方式计算的:

  1. 击球手列 - 击球手“X”的总行数;
  2. 结果列 - 带有“X”的结果总数;
  3. 第 2 点。/第 1 点。确定每个结果的概率;
  4. 重复上述步骤以确定保龄球概率

来自虚拟数据的最终数据帧应类似于:

data = {'Batsman':['Tom', 'Nick', 'Nick', 'Nick', 'Tom', 'Nick', 'Nick', 'Pete', 'Pete'],
        'zero_prob_bat':[0,0.4,0.4,0.4,0,0.4,0.4,0.5,0.5],
        'one_prob_bat':[0.5,0.4,0.4,0.4,0.5,0.4,0.4,0,0],
        'two_prob_bat':[0,0,0,0,0,0,0,0.5,0.5],
        'three_prob_bat':[0,0,0,0,0,0,0,0,0],
        'four_prob_bat':[0,0.2,0.2,0.2,0,0.2,0.2,0,0],
        'six_prob_bat':[0,0,0,0,0,0,0,0,0],
        'out_prob_bat':[0.5,0,0,0,0.5,0,0,0,0],
        'Bowler':['Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Ben', 'Ben'],
        'zero_prob_bowl':[0.1428,0.1428,0.1428,0.1428,0.1428,0.1428,0.1428,0.5,0.5],
        'one_prob_bowl':[0.4285,0.4285,0.4285,0.4285,0.4285,0.4285,0.4285,0,0],
        'two_prob_bowl':[0,0,0,0,0,0,0,0.5,0.5],
        'three_prob_bowl':[0,0,0,0,0,0,0,0,0],
        'four_prob_bowl':[0.1428,0.1428,0.1428,0.1428,0.1428,0.1428,0.1428,0,0],
        'six_prob_bowl':[0.1428,0.1428,0.1428,0.1428,0.1428,0.1428,0.1428,0,0],
        'out_prob_bowl':[0.1428,0.1428,0.1428,0.1428,0.1428,0.1428,0.1428,0,0],
        'Outcome':[1, 0, 1, 'Wide', 'Out', 4, 1, 2, 0]
}

一个问题是,我的原始数据集有 600 多个唯一名称。我可以手动 .groupby 击球手/投球手列中的每个唯一名称,但这不是一个可扩展的解决方案,因为会不断添加新名称。

我很想:-

  1. .计算击球手/投球手每个唯一名称的实例数;
  2. .计算每个独特的击球手/投球手的不同结果的数量;
  3. 执行查找以匹配每个击球手/投球手旁边的概率;

但是,由于我的数据集大小将不断增长,我对实现答案here 中详述的查找功能持谨慎态度。在过去,当我使用 excel/CSV 时,这也产生了许多问题,所以我不想落入任何类似的陷阱。

如果有人能解释他们将如何解决这个问题,以便我有目标,那将不胜感激。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    不确定这与您的实际数据集有多大的比例关系,但我发现很难想出比在 "Batsman" 列上使用 groupby 然后在分组的 "Outcome" 列上使用 value_counts 更好的解决方案。示例:

    data = {'Batsman':['Tom', 'Nick', 'Nick', 'Nick', 'Tom', 'Nick', 'Nick', 'Pete', 'Pete'],
                'Outcome':[1, 0, 1, 'Wide', 'Out', 4, 1, 2, 0],
                'Bowler':['Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Ben', 'Ben']
        }
    
    grouped_data = df.groupby('Batsman')['Outcome'].value_counts(normalize=True)
    print(grouped_data)
    

    输出:

    Batsman  Outcome
    Nick     1          0.4
             0          0.2
             4          0.2
             Wide       0.2
    Pete     0          0.5
             2          0.5
    Tom      1          0.5
             Out        0.5
    Name: Outcome, dtype: float64
    

    请注意,我们不需要手动对每个唯一名称进行分组,因为 groupby 已经为我们这样做了。

    只需替换groupby 调用中的"Batsman" 字符串,即可将相同的逻辑应用于"Bowler" 列。

    【讨论】:

    • 谢谢@jfaccioni。这看起来解决了主要问题,即获得每个结果的概率。但是,是否可以保留原始数据帧的顺序?即汤姆、尼克、尼克等。我认为使用 groupby 和 sort=False 这可能吗?此外,实际上是否有可能添加新列,即 zero_prob、one_prob 来识别击球手/结果并在 grouped_data 值中分配?
    【解决方案2】:

    我认为这回答了你的问题...

    import pandas as pd
    import numpy as np
    
    data = {'Batsman':['Tom', 'Nick', 'Nick', 'Nick', 'Tom', 'Nick', 'Nick', 'Pete', 'Pete'],
                'Outcome':[1, 0, 1, 'Wide', 'Out', 4, 1, 2, 0],
                'Bowler':['Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Bill', 'Ben', 'Ben']
        }
        
    df = pd.DataFrame(data)
    display(df)
    batsman = df['Batsman'].unique()
    bowler = df['Bowler'].unique()
    print(sorted(batsman))
    print(sorted(bowler))
    
    final_df = pd.DataFrame()
    for man in batsman:
        df1 = df[df['Batsman'] == man]
        count_man = len(df1)
        
        outcome = df['Outcome'].unique()
        count_outcome = len(outcome)
        
        batsman_prob = np.array(count_man/count_outcome)
        batsman_df = pd.DataFrame(data=[batman_prob], columns=[man], index=['Batsman'])
        
        final_df = pd.concat([final_df, batsman_df, ], axis=1)
    
    for man in bowler:
        
        df1 = df[df['Bowler'] == man]
        count_man = len(df1)
        
        outcome = df['Outcome'].unique()
        count_outcome = len(outcome)
        
        bowler_prob = np.array(count_man/count_outcome)
        bowler_df = pd.DataFrame(data=[bowler_prob], columns=[man], index=['Bowler'])
        
        final_df = pd.concat([final_df, bowler_df, ], axis=1)
        
    display(final_df)
    

    这是输出:

                Tom         Nick        Pete        Bill        Ben
    Batsman     0.333333    0.333333    0.333333    NaN         NaN
    Bowler      NaN         NaN         NaN         1.166667    0.333333
    

    【讨论】:

    • 很遗憾没有。上面的输出告诉我每个人都是击球手或投球手的概率(尽管我不确定为什么比尔的值 > 1)。所需的输出是问题的第二个数据帧。有一些有用的代码我可能能够适应实现这一目标,所以谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多