【问题标题】:Pandas crosstab - How to print rows/columns for values that don't exist in the data sets?Pandas 交叉表 - 如何打印数据集中不存在的值的行/列?
【发布时间】:2017-03-09 21:33:43
【问题描述】:

我充其量是 pandas 的初学者,我无法在任何地方找到解决此问题的方法。

假设我有两个变量:variable1,variable2。

它们可以具有以下预定义值:

variable1 = ['1', '4', '9', '15', '20']
variable2 = ['2', '5', '6']

但是,当前数据集只有其中一些值:

df = pd.DataFrame({variable1 : ['1', '9', '20'],
                  variable2 : ['2', '2', '6']})

交叉变量时:

pd.crosstab(df.variable1, df.variable2)

我明白了:

variable2  2  6
variable1      
1          1  0
20         0  1
9          1  0

有没有办法将所有可能的分类值放在列和行中,即使当前数据集没有所有这些值?目标是在使用更新的数据集运行脚本时拥有相同大小的表,该数据集可能具有先前数据集中不存在的值。

【问题讨论】:

    标签: python python-3.x pandas crosstab reindex


    【解决方案1】:

    使用DataFrame.reindex:

    variable1 = ['1', '4', '9', '15', '20']
    variable2 = ['2', '5', '6']
    
    
    df = pd.DataFrame({'variable1' : ['1', '9', '20'],
                      'variable2' : ['2', '2', '6']})
    
    print (df)                  
      variable1 variable2
    0         1         2
    1         9         2
    2        20         6
    
    df = pd.crosstab(df.variable1, df.variable2)
    df = df.reindex(index=variable1, columns=variable2, fill_value=0)
    print (df)
    variable2  2  5  6
    variable1         
    1          1  0  0
    4          0  0  0
    9          1  0  0
    15         0  0  0
    20         0  0  1
    

    from collections import OrderedDict
    
    
    valuelabels = OrderedDict([('S8', [['1', 'Medical oncology'], 
                                       ['2', 'Hematology'], 
                                       ['3', 'Hematology/Oncology'], 
                                       ['4', 'Other']]), 
                               ('S9', [['1', 'Academic / Teaching Hospital'], 
                                       ['2', 'Community-Based Solo Private Practice'], 
                                       ['3', 'Community-Based Group Private Practice (record practice size )'], ['4', 'Community Non-Teaching Hospital'], 
                                       ['5', 'Comprehensive Cancer Center'], 
                                       ['6', 'Other (specify)']])])
    #print (valuelabels)
    
    
    df = pd.DataFrame({'variable1' : ['1', '2', '4'],
                      'variable2' : ['2', '3', '1']})
    
    table = pd.crosstab(df.variable1, df.variable2)      
    print (table)
    variable2  1  2  3
    variable1         
    1          0  1  0
    2          0  0  1
    4          1  0  0
    
    d1 = dict(list(zip([a[0] for a in valuelabels['S8']], [a[1] for a in valuelabels['S8']])))
    print (d1)
    {'4': 'Other', '1': 'Medical oncology', '2': 'Hematology', '3': 'Hematology/Oncology'}
    
    d2 = dict(list(zip([a[0] for a in valuelabels['S9']], [a[1] for a in valuelabels['S9']])))
    print (d2)
    {'1': 'Academic / Teaching Hospital', 
    '3': 'Community-Based Group Private Practice (record practice size )', 
    '4': 'Community Non-Teaching Hospital', 
    '6': 'Other (specify)', 
    '2': 'Community-Based Solo Private Practice', 
    '5': 'Comprehensive Cancer Center'}
    
    table = table.reindex(index=[a[0] for a in valuelabels['S8']], 
                          columns=[a[0] for a in valuelabels['S9'], fill_value=0)
    print (table)
    variable2  1  2  3  4  5  6
    variable1                  
    1          0  1  0  0  0  0
    2          0  0  1  0  0  0
    3          0  0  0  0  0  0
    4          1  0  0  0  0  0
    
    table.index = table.index.to_series().map(d1).values
    table.columns = table.columns.to_series().map(d2).values
    
    print (table)
                         Academic / Teaching Hospital  \
    Medical oncology                                0   
    Hematology                                      0   
    Hematology/Oncology                             0   
    Other                                           1   
    
                         Community-Based Solo Private Practice  \
    Medical oncology                                         1   
    Hematology                                               0   
    Hematology/Oncology                                      0   
    Other                                                    0   
    
                         Community-Based Group Private Practice (record practice size )  \
    Medical oncology                                                     0                
    Hematology                                                           1                
    Hematology/Oncology                                                  0                
    Other                                                                0                
    
                         Community Non-Teaching Hospital  \
    Medical oncology                                   0   
    Hematology                                         0   
    Hematology/Oncology                                0   
    Other                                              0   
    
                         Comprehensive Cancer Center  Other (specify)  
    Medical oncology                               0                0  
    Hematology                                     0                0  
    Hematology/Oncology                            0                0  
    Other                                          0                0  
    

    【讨论】:

    • 完美运行!谢谢!
    • 很高兴能帮到你!
    • 我又被卡住了——现在我无法使用 pd.crosstab 参数传递值标签——行名和列名。我得到AssertionError: arrays and names must have the same length。有没有办法解决这个问题?
    • table = pd.crosstab(df.S8, df.S9) table = table.reindex(index=[a[0] for a in valuelabels['S8']], columns=[a[0] for a in valuelabels['S9']], fill_value=0) 我从这个开始,然后尝试在 pd.crosstab 中添加值标签作为参数,最终得到了那个错误。如果我传递了数据集中实际存在的标签数量,一切正常。
    • 真的很有趣。交叉表替代 df = df.pivot_table(index='variable1', columns='variable2', aggfunc=len, fill_value=0) 的工作原理是什么?
    【解决方案2】:

    您可以使用重新索引:

    ct = pd.crosstab(df.variable1, df.variable2)
    ct.reindex(index=variable1, columns=variable2).fillna(0).astype('int')
    Out: 
    variable2  2  5  6
    variable1         
    1          1  0  0
    4          0  0  0
    9          1  0  0
    15         0  0  0
    20         0  0  1
    

    【讨论】:

      【解决方案3】:
      def TargetPercentByNominal (
       targetVar,       # target variable
       predictor):      # nominal predictor
      
      countTable = pandas.crosstab(index = predictor, columns = targetVar, margins = True, dropna = True)
        x = countTable.drop('All', 1)
        percentTable = countTable.div(x.sum(1), axis='index')*100
      
        print("Frequency Table: \n")
        print(countTable)
        print( )
        print("Percent Table: \n")
        print(percentTable)
      
        return
      

      【讨论】:

      • 不要只是发布代码 - 请解释其背后的动机
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-20
      • 2020-01-11
      • 2016-12-10
      • 1970-01-01
      • 2020-09-01
      相关资源
      最近更新 更多