【问题标题】:unique combinations of values in selected columns in pandas data frame and count熊猫数据框和计数中选定列中值的唯一组合
【发布时间】:2016-05-18 01:36:15
【问题描述】:

我在 pandas 数据框中的数据如下:

df1 = pd.DataFrame({'A':['yes','yes','yes','yes','no','no','yes','yes','yes','no'],
                   'B':['yes','no','no','no','yes','yes','no','yes','yes','no']})

所以,我的数据看起来像这样

----------------------------
index         A        B
0           yes      yes
1           yes       no
2           yes       no
3           yes       no
4            no      yes
5            no      yes
6           yes       no
7           yes      yes
8           yes      yes
9            no       no
-----------------------------

我想将其转换为另一个数据框。预期的输出可以显示在以下 python 脚本中:

output = pd.DataFrame({'A':['no','no','yes','yes'],'B':['no','yes','no','yes'],'count':[1,2,4,3]})

所以,我的预期输出是这样的

--------------------------------------------
index      A       B       count
--------------------------------------------
0         no       no        1
1         no      yes        2
2        yes       no        4
3        yes      yes        3
--------------------------------------------

其实我可以通过下面的命令找到所有的组合并统计它们:mytable = df1.groupby(['A','B']).size()

但是,事实证明,这些组合在单个列中。我想将组合中的每个值分成不同的列,并为计数结果再添加一列。有可能这样做吗?我可以有你的建议吗?提前谢谢你。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以在列“A”和“B”上groupby 并调用size,然后调用reset_indexrename 生成的列:

    In [26]:
    
    df1.groupby(['A','B']).size().reset_index().rename(columns={0:'count'})
    Out[26]:
         A    B  count
    0   no   no      1
    1   no  yes      2
    2  yes   no      4
    3  yes  yes      3
    

    更新

    稍微解释一下,通过对 2 列进行分组,这对 A 和 B 值相同的行进行分组,我们调用 size 它返回唯一组的数量:

    In[202]:
    df1.groupby(['A','B']).size()
    
    Out[202]: 
    A    B  
    no   no     1
         yes    2
    yes  no     4
         yes    3
    dtype: int64
    

    所以现在要恢复分组的列,我们调用reset_index

    In[203]:
    df1.groupby(['A','B']).size().reset_index()
    
    Out[203]: 
         A    B  0
    0   no   no  1
    1   no  yes  2
    2  yes   no  4
    3  yes  yes  3
    

    这会恢复索引,但大小聚合会变成生成列0,所以我们必须重命名它:

    In[204]:
    df1.groupby(['A','B']).size().reset_index().rename(columns={0:'count'})
    
    Out[204]: 
         A    B  count
    0   no   no      1
    1   no  yes      2
    2  yes   no      4
    3  yes  yes      3
    

    groupby 确实接受了我们可以设置为 False 的参数 as_index,因此它不会使分组列成为索引,但这会生成一个 series 并且您仍然需要恢复索引等等....:

    In[205]:
    df1.groupby(['A','B'], as_index=False).size()
    
    Out[205]: 
    A    B  
    no   no     1
         yes    2
    yes  no     4
         yes    3
    dtype: int64
    

    【讨论】:

    • 注意:如stackoverflow.com/a/54364400/1224158 中所述,您可以用count() 代替size() 来忽略NaN 并返回一个数据帧
    • 也许更清楚一点:在size() 之后,使用rename("count")。因此,size() 生成的 Series 现在将 name 属性设置为“count”,name 属性将是 reset_index() 生成的 DataFrame 的列名。
    【解决方案2】:

    在 Pandas 1.1.0 中,您可以将方法 value_counts 与 DataFrames 一起使用:

    df.value_counts() # or df[['A', 'B']].value_counts()
    

    结果:

    A    B
    yes  no     4
         yes    3
    no   yes    2
         no     1
    dtype: int64
    

    将索引转换为列并按值计数排序:

    df.value_counts(ascending=True).reset_index(name='count')
    

    结果:

         A    B  count
    0   no   no      1
    1   no  yes      2
    2  yes  yes      3
    3  yes   no      4
    

    【讨论】:

      【解决方案3】:

      有点相关,我一直在寻找独特的组合,我想出了这个方法:

      def unique_columns(df,columns):
      
          result = pd.Series(index = df.index)
      
          groups = meta_data_csv.groupby(by = columns)
          for name,group in groups:
             is_unique = len(group) == 1
             result.loc[group.index] = is_unique
      
          assert not result.isnull().any()
      
          return result
      

      如果您只想断言所有组合都是唯一的:

      df1.set_index(['A','B']).index.is_unique
      

      【讨论】:

      • 不知道set_index()。继续尝试使用groupby() 将具有特定公共列对的行组合在一起。太棒了,谢谢!
      【解决方案4】:

      我还没有对此进行时间测试,但尝试起来很有趣。基本上将两列转换为一列元组。现在将 that 转换为数据框,执行 'value_counts()' 找到唯一元素 对它们进行计数。再次摆弄 zip 并将列按您想要的顺序排列。您可能可以使步骤更优雅,但对于这个问题,使用元组对我来说似乎更自然

      b = pd.DataFrame({'A':['yes','yes','yes','yes','no','no','yes','yes','yes','no'],'B':['yes','no','no','no','yes','yes','no','yes','yes','no']})
      
      b['count'] = pd.Series(zip(*[b.A,b.B]))
      df = pd.DataFrame(b['count'].value_counts().reset_index())
      df['A'], df['B'] = zip(*df['index'])
      df = df.drop(columns='index')[['A','B','count']]
      

      【讨论】:

        【解决方案5】:

        将@EdChum 非常好的答案放入函数count_unique_index。 独特的方法仅适用于 pandas 系列,不适用于数据框。 下面的函数重现了 R 中 unique 函数的行为:

        unique 返回类似于 x 的向量、数据框或数组,但删除了重复的元素/行。

        并根据 OP 的要求添加出现次数。

        def count_unique_index(df, by):                                                                                                                                                 
            return df.groupby(by).size().reset_index().rename(columns={0:'count'})                                                                                                      
        
        df1 = pd.DataFrame({'A':['yes','yes','yes','yes','no','no','yes','yes','yes','no'],                                                                                             
                            'B':['yes','no','no','no','yes','yes','no','yes','yes','no']})   
                                                                                                                                                                                         
        count_unique_index(df1, ['A','B'])                                                                                                                                              
             A    B  count                                                                                                                                                                  
        0   no   no      1                                                                                                                                                                  
        1   no  yes      2                                                                                                                                                                  
        2  yes   no      4                                                                                                                                                                  
        3  yes  yes      3
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-16
          • 2016-07-14
          • 1970-01-01
          • 1970-01-01
          • 2017-05-30
          • 1970-01-01
          相关资源
          最近更新 更多