创建一个计算关系记录的对称矩阵
Create a symmetric matrix that counts the relational records
我想通过基于另一列(ID
)的一列(Value
)计算所有可能的成对关系的数量。
示例数据框:
ID Value
0 1 A
1 1 A
2 1 A
3 1 B
4 1 C
5 2 B
6 2 C
7 2 C
生成示例数据框:
import pandas as pd
df = pd.DataFrame({'ID' : {0: 1, 1: 1, 2: 1, 3: 1, 4: 1,
5: 2, 6: 2, 7: 2},
'Value' : {0: 'A', 1: 'A', 2: 'A', 3: 'B', 4: 'C',
5: 'B', 6: 'C', 7: 'C'}
})
应该对 ID=1
和 ID=2
进行成对计数。
可能的配对,其中 ID=1
(A,A), (A,A), (A,B), (A,C),
(A,A), (A,A), (A,B), (A,C),
(A,A), (A,A), (A,B), (A,C),
(B,A), (B,A), (B,A), (B,C),
(C,A), (C,A), (C,A), (C,B),
可能的配对,其中 ID=2
(B,C), (B,C)
(C,B), (C,C)
(C,B), (C,C)
预期数据帧:
A B C
A 6 3 3
B 3 0 3
C 3 3 2
我目前得到的(见下面与其他 Whosebug 问题的关系):
df = pd.merge(df, df, on='ID')
df = pd.crosstab(df['Value_x'], df['Value_y']).rename_axis(None).rename_axis(None, axis=1)
print (df)
错误的输出:
A B C
A 9 3 3
B 3 2 3
C 3 3 5
正如您可能发现的那样,这个问题主要与对角醛有关。我假设我必须专注于合并方面来处理提议的场景。但是,到目前为止我无法处理:(有什么建议吗?
提前致谢!
相关问题:
与 有各种相似之处。但是,该问题的期望值可能略有错误。 (A, A) = 0, (B,B) = 0, (C,C) = 0 的情况应为 0,因为根据该问题,它们在两种情况下(ID=1 或 ID=2)都不存在.如果我们只想计算那些条件 > AB、AC、BA、BC、CA、CB(来自 ID=1)和 BC、CB(来自 ID=2)。另一方面,这里的主要区别在于对角线。
您可以使用 itertool.permutations
但将其应用于每个组:
from itertools import permutations
out = pd.DataFrame()
for _, g in df.groupby("ID"):
d = pd.DataFrame(permutations(g["Value"], 2), columns=["x", "y"])
x = pd.crosstab(d["x"], d["y"]).rename_axis(None).rename_axis(None, axis=1)
out = out.add(x, fill_value=0)
print(out.astype(int))
打印:
A B C
A 6 3 3
B 3 0 3
C 3 3 2
如果您需要访问排列,您也可以在一个框架中构建所有排列,然后获取整个交叉表。
import pandas as pd
from itertools import permutations
df = pd.DataFrame({'ID': {0: 1, 1: 1, 2: 1, 3: 1, 4: 1,
5: 2, 6: 2, 7: 2},
'Value': {0: 'A', 1: 'A', 2: 'A', 3: 'B', 4: 'C',
5: 'B', 6: 'C', 7: 'C'}
})
perms = df.groupby('ID')['Value'] \
.apply(lambda s: pd.DataFrame(permutations(s, 2), columns=['x', 'y']))
new_df = pd.crosstab(perms.x, perms.y) \
.rename_axis(None, axis=1) \
.rename_axis(None, axis=0)
# For Display
print(new_df)
print()
print(perms)
输出
new_df:
A B C
A 6 3 3
B 3 0 3
C 3 3 2
烫发:
x y
ID
1 0 A A
1 A A
2 A B
3 A C
4 A A
5 A A
6 A B
7 A C
8 A A
9 A A
10 A B
11 A C
12 B A
13 B A
14 B A
15 B C
16 C A
17 C A
18 C A
19 C B
2 0 B C
1 B C
2 C B
3 C C
4 C B
5 C C
让我们在crosstab
之后尝试dot
,然后减去自身对~
s = pd.crosstab(df.ID,df.Value)
out = s.T.dot(s)
np.fill_diagonal(out.values, out.values.diagonal() - s.sum())
out
Value A B C
Value
A 6 3 3
B 3 0 3
C 3 3 2
我想通过基于另一列(ID
)的一列(Value
)计算所有可能的成对关系的数量。
示例数据框:
ID Value
0 1 A
1 1 A
2 1 A
3 1 B
4 1 C
5 2 B
6 2 C
7 2 C
生成示例数据框:
import pandas as pd
df = pd.DataFrame({'ID' : {0: 1, 1: 1, 2: 1, 3: 1, 4: 1,
5: 2, 6: 2, 7: 2},
'Value' : {0: 'A', 1: 'A', 2: 'A', 3: 'B', 4: 'C',
5: 'B', 6: 'C', 7: 'C'}
})
应该对 ID=1
和 ID=2
进行成对计数。
可能的配对,其中 ID=1
(A,A), (A,A), (A,B), (A,C),
(A,A), (A,A), (A,B), (A,C),
(A,A), (A,A), (A,B), (A,C),
(B,A), (B,A), (B,A), (B,C),
(C,A), (C,A), (C,A), (C,B),
可能的配对,其中 ID=2
(B,C), (B,C)
(C,B), (C,C)
(C,B), (C,C)
预期数据帧:
A B C
A 6 3 3
B 3 0 3
C 3 3 2
我目前得到的(见下面与其他 Whosebug 问题的关系):
df = pd.merge(df, df, on='ID')
df = pd.crosstab(df['Value_x'], df['Value_y']).rename_axis(None).rename_axis(None, axis=1)
print (df)
错误的输出:
A B C
A 9 3 3
B 3 2 3
C 3 3 5
正如您可能发现的那样,这个问题主要与对角醛有关。我假设我必须专注于合并方面来处理提议的场景。但是,到目前为止我无法处理:(有什么建议吗? 提前致谢!
相关问题:
与
您可以使用 itertool.permutations
但将其应用于每个组:
from itertools import permutations
out = pd.DataFrame()
for _, g in df.groupby("ID"):
d = pd.DataFrame(permutations(g["Value"], 2), columns=["x", "y"])
x = pd.crosstab(d["x"], d["y"]).rename_axis(None).rename_axis(None, axis=1)
out = out.add(x, fill_value=0)
print(out.astype(int))
打印:
A B C
A 6 3 3
B 3 0 3
C 3 3 2
如果您需要访问排列,您也可以在一个框架中构建所有排列,然后获取整个交叉表。
import pandas as pd
from itertools import permutations
df = pd.DataFrame({'ID': {0: 1, 1: 1, 2: 1, 3: 1, 4: 1,
5: 2, 6: 2, 7: 2},
'Value': {0: 'A', 1: 'A', 2: 'A', 3: 'B', 4: 'C',
5: 'B', 6: 'C', 7: 'C'}
})
perms = df.groupby('ID')['Value'] \
.apply(lambda s: pd.DataFrame(permutations(s, 2), columns=['x', 'y']))
new_df = pd.crosstab(perms.x, perms.y) \
.rename_axis(None, axis=1) \
.rename_axis(None, axis=0)
# For Display
print(new_df)
print()
print(perms)
输出
new_df:
A B C
A 6 3 3
B 3 0 3
C 3 3 2
烫发:
x y
ID
1 0 A A
1 A A
2 A B
3 A C
4 A A
5 A A
6 A B
7 A C
8 A A
9 A A
10 A B
11 A C
12 B A
13 B A
14 B A
15 B C
16 C A
17 C A
18 C A
19 C B
2 0 B C
1 B C
2 C B
3 C C
4 C B
5 C C
让我们在crosstab
之后尝试dot
,然后减去自身对~
s = pd.crosstab(df.ID,df.Value)
out = s.T.dot(s)
np.fill_diagonal(out.values, out.values.diagonal() - s.sum())
out
Value A B C
Value
A 6 3 3
B 3 0 3
C 3 3 2