如何在pandas-python中计算数据框中值的条件概率?

11

我想计算在评分列中评分为('A','B','C')的条件概率。

    company     model    rating   type
0   ford       mustang     A      coupe
1   chevy      camaro      B      coupe
2   ford       fiesta      C      sedan
3   ford       focus       A      sedan
4   ford       taurus      B      sedan
5   toyota     camry       B      sedan

输出:

Prob(rating=A) = 0.333333 
Prob(rating=B) = 0.500000 
Prob(rating=C) = 0.166667 

Prob(type=coupe|rating=A) = 0.500000 
Prob(type=sedan|rating=A) = 0.500000 
Prob(type=coupe|rating=B) = 0.333333 
Prob(type=sedan|rating=B) = 0.666667 
Prob(type=coupe|rating=C) = 0.000000 
Prob(type=sedan|rating=C) = 1.000000 

有任何帮助,请谢谢..!!


4
好的,做吧 :)。 Prob(type=coupe|rating=A) = Prob(type=coupe and rating=A) / Prob(rating=A) 可以翻译为:当评级为A时,两门轿车的概率=两门轿车和评级为A的概率/评级为A的概率。 - cel
使用pd.crosstab怎么样? - linello
5个回答

20

您可以使用.groupby()和内置的.div()函数:

rating_probs = df.groupby('rating').size().div(len(df))

rating
A    0.333333
B    0.500000
C    0.166667

以及条件概率:

df.groupby(['type', 'rating']).size().div(len(df)).div(rating_probs, axis=0, level='rating')

coupe  A         0.500000
       B         0.333333
sedan  A         0.500000
       B         0.666667
       C         1.000000

我认为level参数应该是0,而不是1。 - Patthebug
你试过了吗?当我将上面的工作版本更改为level=0时,会出现缺失值。 rating_probs必须与rating级别保持一致,该级别为1级。你还可以将level=1更改为level='rating'以更好地理解为什么这样做是有效的。只需相应地进行编辑即可。 - Stefan
有趣。我使用 level=1 得到了结果,但是这些结果是不正确的。将其更改为 level=0 给了我正确的条件概率值。 - Patthebug
只是想澄清一下 - 你是在说上面的结果是错误的,还是你使用上述代码得到了不同的结果? - Stefan
我输入了90行,但只返回了89行。 - Ramin Melikov
显示剩余2条评论

4
你可以使用groupby
In [2]: df = pd.DataFrame({'company': ['ford', 'chevy', 'ford', 'ford', 'ford', 'toyota'],
                     'model': ['mustang', 'camaro', 'fiesta', 'focus', 'taurus', 'camry'],
                     'rating': ['A', 'B', 'C', 'A', 'B', 'B'],
                     'type': ['coupe', 'coupe', 'sedan', 'sedan', 'sedan', 'sedan']})

In [3]: df.groupby('rating').count()['model'] / len(df)
Out[3]:
rating
A    0.333333
B    0.500000
C    0.166667
Name: model, dtype: float64

In [4]: (df.groupby(['rating', 'type']).count() / df.groupby('rating').count())['model']
Out[4]:
rating  type
A       coupe    0.500000
        sedan    0.500000
B       coupe    0.333333
        sedan    0.666667
C       sedan    1.000000
Name: model, dtype: float64

3
你需要添加reindex函数,为缺失的数据对添加0值:
mux = pd.MultiIndex.from_product([df['rating'].unique(), df['type'].unique()])
s = (df.groupby(['rating', 'type']).count() / df.groupby('rating').count())['model']
s = s.reindex(mux, fill_value=0)
print (s)
A  coupe    0.500000
   sedan    0.500000
B  coupe    0.333333
   sedan    0.666667
C  coupe    0.000000
   sedan    1.000000
Name: model, dtype: float64

还有另一种解决方案,感谢Zero提供:

s.unstack(fill_value=0).stack()

s.unstack(fill_value=0).stack() 这样做可以吗? - Zero

1

pd.crosstab(df.type, df.rating, margins=True, normalize="index")

的翻译结果是:使用 pd.crosstab 函数对 df.type 和 df.rating 进行交叉统计,同时加入总计列和行,并按行进行归一化处理。
   rating     A       B       C
   type                           
   coupe   0.500000  0.5  0.000000
   sedan   0.250000  0.5  0.250000
   All     0.333333  0.5  0.166667

在这里,“全部”行为您提供了A、B和C的概率,现在是条件概率。 pd.crosstab(df.type, df.rating, margins=True, normalize="columns")
 rating   A      B       C     All
 type                                
 coupe   0.5  0.333333  0.0  0.333333
 sedan   0.5  0.666667  1.0  0.666667

这里有一个表格,展示了条件概率的例子。例如,在“coupe”行和“A”列中,给定类型为coupe且评级为A的条件概率为0.5。

Prob(type=coupe|rating=A) = 0.5

这是一种非常干净简洁的方法!只需要学习交叉表函数的工作原理。非常有用。 - DataBach

-1
首先,将其转换为Pandas数据框。这样做可以利用Pandas的groupby方法。
collection = {"company": ["ford", "chevy", "ford", "ford", "ford", "toyota"],
              "model": ["mustang", "camaro", "fiesta", "focus", "taurus", "camry"],
              "rating": ["A", "B", "C", "A", "B", "B"],
              "type": ["coupe", "coupe", "sedan", "sedan", "sedan", "sedan"]}

df = pd.DataFrame(collection)

然后,根据事件(即评分)进行分组。

df_s = df.groupby('rating')['type'].value_counts() / df.groupby('rating')['type'].count()
df_f = df_s.reset_index(name='cpt')
df_f.head()  # your conditional probability table

我输入了90行,但只返回了89行。 - Ramin Melikov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接