如何根据 PySpark 数据框所有成对列的值制作混淆矩阵?
How to make a confusion matrix based on values from all the pairs of columns of a PySpark dataframe?
我有一个 PySpark 数据框
simpleData = [("person0",1, 1, 0), \
("person1",1, 1, 1), \
("person2",1, 0, 0), \
("person3",0 ,0, 0 ), \
]
columns= ['persons_name','A', 'B', 'C']
exp = spark.createDataFrame(data = simpleData, schema = columns)
exp.show()
它只包含二进制值(0 和 1)
这看起来像-
+------------+---+---+---+
|persons_name| A| B| C|
+------------+---+---+---+
| person0| 1| 1| 0|
| person1| 1| 1| 1|
| person2| 1| 0| 0|
| person3| 0| 0| 0|
+------------+---+---+---+
我们需要用零初始化混淆矩阵,例如,
+---+---+---+---+
| | A| B| C|
+---+---+---+---+
| A| 0| 0| 0|
| B| 0| 0| 0|
| C| 0| 0| 0|
+---+---+---+---+
现在我想用以下方式填充混淆矩阵-
对于数据框中的每一行 exp,我想为数据框中所有值 = 1 的列对增加混淆矩阵的计数器。
例如,对于 person0,只有 1 对列 A 和 B,其值 = 1。因此我们增加混淆矩阵的值在 ( A、B)和(B、A)。
这看起来像-
+---+---+---+---+
| | A| B| C|
+---+---+---+---+
| A| 0| 1| 0|
| B| 1| 0| 0|
| C| 0| 0| 0|
+---+---+---+---+
对于 person1,有 3 对列,(A, B)、(A, C) 和 (B, C),它们的值为 1。所以我们在 (A, B)、(B, A)、(A, C)、(C, A)、(B, C) 和 (C, B) 处增加混淆矩阵的值。
现在更新后的混淆矩阵看起来像-
+---+---+---+---+
| | A| B| C|
+---+---+---+---+
| A| 0| 2| 1|
| B| 2| 0| 1|
| C| 1| 1| 0|
+---+---+---+---+
person2 和 person3 没有这样的对。所以我们不更新混淆矩阵。
最终的混淆矩阵看起来像-
+---+---+---+---+
| | A| B| C|
+---+---+---+---+
| A| 0| 2| 1|
| B| 2| 0| 1|
| C| 1| 1| 0|
+---+---+---+---+
PySpark 如何实现?
假设您的原始数据框是一个包含列 A, B, C
的矩阵,可以通过将原始矩阵与其自身的转置相乘来计算混淆矩阵。换句话说,行 A
列 B
的条目只是 A
列和 B
的点积,除了对角线 ,因此您基本上可以在列上进行嵌套循环,计算每对列的点积。
此外,一般情况下,列数应该足够小以便在本地主机上易于管理,您可以将结果收集到二维列表或 numpy 数组中:
import numpy as np
import pyspark.sql.functions as f
cols = ['A', 'B', 'C']
res = np.array([
[exp.agg(f.sum(f.col(x) * f.col(y))).first()[0] if x != y else 0 for y in cols]
for x in cols
])
res
#[[0 2 1]
# [2 0 1]
# [1 1 0]]
我有一个 PySpark 数据框
simpleData = [("person0",1, 1, 0), \
("person1",1, 1, 1), \
("person2",1, 0, 0), \
("person3",0 ,0, 0 ), \
]
columns= ['persons_name','A', 'B', 'C']
exp = spark.createDataFrame(data = simpleData, schema = columns)
exp.show()
它只包含二进制值(0 和 1) 这看起来像-
+------------+---+---+---+
|persons_name| A| B| C|
+------------+---+---+---+
| person0| 1| 1| 0|
| person1| 1| 1| 1|
| person2| 1| 0| 0|
| person3| 0| 0| 0|
+------------+---+---+---+
我们需要用零初始化混淆矩阵,例如,
+---+---+---+---+
| | A| B| C|
+---+---+---+---+
| A| 0| 0| 0|
| B| 0| 0| 0|
| C| 0| 0| 0|
+---+---+---+---+
现在我想用以下方式填充混淆矩阵- 对于数据框中的每一行 exp,我想为数据框中所有值 = 1 的列对增加混淆矩阵的计数器。
例如,对于 person0,只有 1 对列 A 和 B,其值 = 1。因此我们增加混淆矩阵的值在 ( A、B)和(B、A)。 这看起来像-
+---+---+---+---+
| | A| B| C|
+---+---+---+---+
| A| 0| 1| 0|
| B| 1| 0| 0|
| C| 0| 0| 0|
+---+---+---+---+
对于 person1,有 3 对列,(A, B)、(A, C) 和 (B, C),它们的值为 1。所以我们在 (A, B)、(B, A)、(A, C)、(C, A)、(B, C) 和 (C, B) 处增加混淆矩阵的值。
现在更新后的混淆矩阵看起来像-
+---+---+---+---+
| | A| B| C|
+---+---+---+---+
| A| 0| 2| 1|
| B| 2| 0| 1|
| C| 1| 1| 0|
+---+---+---+---+
person2 和 person3 没有这样的对。所以我们不更新混淆矩阵。 最终的混淆矩阵看起来像-
+---+---+---+---+
| | A| B| C|
+---+---+---+---+
| A| 0| 2| 1|
| B| 2| 0| 1|
| C| 1| 1| 0|
+---+---+---+---+
PySpark 如何实现?
假设您的原始数据框是一个包含列 A, B, C
的矩阵,可以通过将原始矩阵与其自身的转置相乘来计算混淆矩阵。换句话说,行 A
列 B
的条目只是 A
列和 B
的点积,除了对角线 ,因此您基本上可以在列上进行嵌套循环,计算每对列的点积。
此外,一般情况下,列数应该足够小以便在本地主机上易于管理,您可以将结果收集到二维列表或 numpy 数组中:
import numpy as np
import pyspark.sql.functions as f
cols = ['A', 'B', 'C']
res = np.array([
[exp.agg(f.sum(f.col(x) * f.col(y))).first()[0] if x != y else 0 for y in cols]
for x in cols
])
res
#[[0 2 1]
# [2 0 1]
# [1 1 0]]