Python中多列的成对频率表

时间:2016-08-02 01:57:14

标签: python pandas

我有一张患者诊断代码表,其中每一行代表一名患者的所有诊断:

      D0             D1        D2       D3       D4        D5       D6  
0          0              0         0        0        0         0        0   
1     I48.91          R60.9    M19.90    Z87.2        0         0        0   
2        496         564.00     477.9        0    J44.9     J30.9      I10   
3        I96          R63.0     Z51.5        0  L97.909    I69.90   F01.50   
4     491.21          428.0    427.31   V58.61        0    I48.91   Z79.01   
5          0              0         0        0        0         0        0   
6      J44.9          F41.9       I10   H61.22        0       Z23        0   
7          0              0         0        0        0         0        0   
8     M48.00          I12.9     N18.9   K59.00        0     N39.0      Z23   
9      I11.9         R41.82     R56.9   E11.49   K59.00         0  J45.901   
10     I11.9          N40.0    F01.50        0    N40.1     J18.9    J44.1   
11     R31.9         M19.90         0   R53.81        0         0        0   
12         0              0         0        0        0         0        0   
13    M48.02         M48.06     I27.2        0   R53.81         0        0   
14     I50.9         M19.90     F41.9   I25.10        0         0        0   
15         0              0         0        0        0         0        0   
16   I69.359         I48.91     R74.8      I10        0  T50.901A    I95.9   

...... 600多名患者,每位患者最多可诊断出15例。 (0&0代表没有诊断)。 我想创建一个成对频率表来计算患者有不同诊断对的次数:

            I48.91                 R60.9                  M19.90
I48.91  count(I48.91)        count(I48.91, R60.9)    count(I48.91, M19.90)
R60.9   count(R60.9, 148.91)
M19.9 ...

我创建了这样的表:

FreqTable = pd.DataFrame(columns=UniqueCodes['DCODE'], index=UniqueCodes['DCODE'])
FreqTable = FreqTable.fillna(0)

Table of Pairwise frequency counts in Python使用嵌套for循环对一列数据执行此操作,但这对于多列来说变得复杂。任何人都有一个很好的pythonese方式来做到这一点?

1 个答案:

答案 0 :(得分:3)

让我们创建一个较小的示例,以便更容易看到每个步骤的效果并验证结果的正确性:

df = pd.DataFrame({'D0': ['0', 'A', 'B', 'C'],
                   'D1': ['B', '0', 'C', 'D'],
                   'D2': ['C','D','0','A']})
#   D0 D1 D2
# 0  0  B  C
# 1  A  0  D
# 2  B  C  0
# 3  C  D  A

由于0将被忽略,让我们将它们改为NaN:

df = df.replace('0', np.nan)

列标签D0D1D2也是可忽略的。这是重要的一排。 让我们stack列制作一个系列:

code = df.stack()
0  D1    B
   D2    C
1  D0    A
   D2    D
2  D0    B
   D1    C
3  D0    C
   D1    D
   D2    A
dtype: object

再次,列标签无关紧要,让我们放弃索引的第二级:

code.index = code.index.droplevel(1)
code.name = 'code'

所以我们最终得到了

0    B
0    C
1    A
1    D
2    B
2    C
3    C
3    D
3    A
Name: code, dtype: object

请注意,此系列的索引引用df中的原始行标签。如果我们join code 自己,那么我们会得到同一行中所有代码对的列表,每行:

code = code.to_frame()
pair = code.join(code, rsuffix='_2')
    #   code code_2
# 0    B      B
# 0    B      C
# 0    C      B
# 0    C      C
# 1    A      A
# 1    A      D
# 1    D      A
# 1    D      D
# 2    B      B
# 2    B      C
# 2    C      B
# 2    C      C
# 3    C      C
# 3    C      D
# 3    C      A
# 3    D      C
# 3    D      D
# 3    D      A
# 3    A      C
# 3    A      D
# 3    A      A

现在通过使用pd.crosstab根据此数据制作频率表来解决问题:

freq = pd.crosstab(pair['code'], pair['code_2'])

全部放在一起:

import numpy as np
import pandas as pd
df = pd.DataFrame({'D0': ['0', 'A', 'B', 'C'],
                   'D1': ['B', '0', 'C', 'D'],
                   'D2': ['C','D','0','A']})
#   D0 D1 D2
# 0  0  B  C
# 1  A  0  D
# 2  B  C  0
# 3  C  D  A

df = df.replace('0', np.nan)
code = df.stack()
code.index = code.index.droplevel(1)
code.name = 'code'
code = code.to_frame()
pair = code.join(code, rsuffix='_2')
freq = pd.crosstab(pair['code'], pair['code_2'])

产量

code_2  A  B  C  D
code              
A       2  0  1  2
B       0  2  2  0
C       1  2  3  1
D       2  0  1  2