Python获取数据帧中所有特征组合的条件概率
我有一个带有一些分类变量的熊猫数据框架。类似这样的事情-Python获取数据帧中所有特征组合的条件概率,python,performance,pandas,numpy,statistics,Python,Performance,Pandas,Numpy,Statistics,我有一个带有一些分类变量的熊猫数据框架。类似这样的事情- >>df 'a', 'x' 'a', 'y' 现在,我想返回一个矩阵,每个级别的条件概率与其他级别一起出现。对于上面的数据帧,它看起来像- [1, 0.5, 0.5], [1, 1, 0], [1, 0, 1] 这三个条目对应于级别“a”、“x”和“y” 这是因为在第一列为“a”的条件下,“x”和“y”出现的概率分别为0.5,依此类推。 我有一些代码可以做到这一点(如下)。然而,问题是它的速度非常慢。速度太慢,以至于我
>>df
'a', 'x'
'a', 'y'
现在,我想返回一个矩阵,每个级别的条件概率与其他级别一起出现。对于上面的数据帧,它看起来像-
[1, 0.5, 0.5],
[1, 1, 0],
[1, 0, 1]
这三个条目对应于级别“a”、“x”和“y”
这是因为在第一列为“a”的条件下,“x”和“y”出现的概率分别为0.5,依此类推。
我有一些代码可以做到这一点(如下)。然而,问题是它的速度非常慢。速度太慢,以至于我想在超时时使用它的应用程序。有没有人有什么建议可以加快速度
df = pd.read_csv('pathToData.csv')
df = df.fillna("null")
cols = 0
col_levels = []
columns = {}
num = 0
for i in df.columns:
cols += len(set(df[i]))
col_levels.append(np.sort(list(set(df[i]))))
for j in np.sort(list(set(df[i]))):
columns[i + '_' + str(j)] = num
num += 1
res = np.eye(cols)
for i in range(len(df.columns)):
for j in range(len(df.columns)):
if i != j:
row_feature = df.columns[i]
col_feature = df.columns[j]
rowLevels = col_levels[i]
colLevels = col_levels[j]
for ii in rowLevels:
for jj in colLevels:
frst = (df[row_feature] == ii) * 1
scnd = (df[col_feature] == jj) * 1
prob = sum(frst*scnd)/(sum(frst) + 1e-9)
frst_ind = columns[row_feature + '_' + ii]
scnd_ind = columns[col_feature + '_' + jj]
res[frst_ind, scnd_ind] = prob
编辑:这里有一个更大的例子:
>>df
'a', 'x', 'l'
'a', 'y', 'l'
'b', 'x', 'l'
这里不同类别的数量是‘a’、‘b’、‘x’、‘y’和‘l’。由于这是5个类别,因此输出矩阵应为5x5。第一行和第一列是“a”以“a”为条件出现的频率。这当然是1(所有对角线也是如此)。第一行和第二列以“a”为条件,“b”的概率是多少。因为“a”和“b”是同一列的一部分,所以这是零。第一行和第三列是以“a”为条件的“x”的概率。我们看到“a”出现两次,但与“x”一起只出现一次。所以,这个概率是0.5。依此类推。我解决这个问题的方法是首先计算数据集中的所有唯一级别。然后循环通过这些级别的笛卡尔乘积。在每个步骤中,过滤数据集以创建条件为真的子集。然后,计算发生事件的子集中的行数。下面是我的代码
import pandas as pd
from itertools import product
from collections import defaultdict
df = pd.DataFrame({
'col1': ['a', 'a', 'b'],
'col2': ['x', 'y', 'x'],
'col3': ['l', 'l', 'l']
})
levels = df.stack().unique()
res = defaultdict(dict)
for event, cond in product(levels, levels):
# create a subset of rows with at least one element equal to cond
conditional_set = df[(df == cond).any(axis=1)]
conditional_set_size = len(conditional_set)
# count the number of rows in the subset where at least one element is equal to event
conditional_event_count = (conditional_set == event).any(axis=1).sum()
res[event][cond] = conditional_event_count / conditional_set_size
result_df = pd.DataFrame(res)
print(result_df)
# OUTPUT
# a b l x y
# a 1.000000 0.000000 1.0 0.500000 0.500000
# b 0.000000 1.000000 1.0 1.000000 0.000000
# l 0.666667 0.333333 1.0 0.666667 0.333333
# x 0.500000 0.500000 1.0 1.000000 0.000000
# y 1.000000 0.000000 1.0 0.000000 1.000000
我确信还有其他更快的方法,但这是我想到的第一件事。数据帧总是有两列吗?你能举一个更大的例子吗?不,数据框可以有任意数量的列。让我来举一个更大的例子。