【问题标题】:Pandas count, sum, average specific range/ value for each rowPandas 每行的计数、总和、平均特定范围/值
【发布时间】:2021-03-07 14:02:42
【问题描述】:

我有大数据,我只想在特定范围内对每一行进行计数、求和、平均。

df = pd.DataFrame({'id0':[10.3,20,30,50,108,110],'id1':[100.5,0,300,570,400,140], 'id2':[-2.6,-3,5,12,44,53], 'id3':[-100.1,4,6,22,12,42]})
     id0    id1   id2    id3
0   10.3  100.5  -2.6 -100.1
1   20.0    0.0  -3.0    4.0
2   30.0  300.0   5.0    6.0
3   50.0  570.0  12.0   22.0
4  108.0  400.0  44.0   12.0
5  110.0  140.0  53.0   42.0

例如,我想计算每行出现的值在 10-100 之间,所以它会得到:

0    1
1    1
2    1
3    3
4    2
5    2
Name: count_10-100, dtype: int64

目前,我通过遍历每一行、横向并使用 groupby 来完成此操作。但这需要一些时间,因为我有 ~500 列和 500000 行

【问题讨论】:

    标签: python pandas pandas-groupby isin


    【解决方案1】:

    您可以在它们之间使用 AND 应用条件,然后沿行(轴 1)使用 sum

    ((df >= 10) & (df <= 100)).sum(axis=1)
    

    输出:

    0    1
    1    1
    2    1
    3    3
    4    2
    5    2
    dtype: int64
    

    对于总和和均值,您可以使用where 应用条件:

    df.where((df >= 10) & (df <= 100)).sum(axis=1)
    df.where((df >= 10) & (df <= 100)).mean(axis=1)
    

    这要归功于@anky,他首先将其作为评论发布:)

    【讨论】:

      【解决方案2】:

      下面总结了您希望在 DataFrame(或 Series,为了完整起见)中计算某些内容的不同情况,以及推荐的方法。

      DataFrame.count 将每列的计数作为一个系列返回,因为非空计数因列而异。 DataFrameGroupBy.size 返回一个系列,因为同一组中的所有列共享相同的行数。 DataFrameGroupBy.count 返回一个 DataFrame,因为同一组中的列之间的非空计数可能不同。 要获取特定列的分组非空计数,请使用 df.groupby(...)['x'].count() 其中“x”是要计数的列。

      #代码示例

      df = pd.DataFrame({
          'A': list('aabbc'), 'B': ['x', 'x', np.nan, 'x', np.nan]})
      s = df['B'].copy()
      
      df
      
         A    B
      0  a    x
      1  a    x
      2  b  NaN
      3  b    x
      4  c  NaN
      
      s
      
      0      x
      1      x
      2    NaN
      3      x
      4    NaN
      Name: B, dtype: object
      Row Count of a DataFrame: len(df), df.shape[0], or len(df.index)
      len(df)
      # 5
      
      df.shape[0]
      # 5
      
      len(df.index)
      # 5
      

      在上述三种方法中,len(df.index)(如其他答案中所述)是最快的。

      注意

      上述所有方法都是常数时间操作,因为它们是简单的属性查找。 df.shape(类似于ndarray.shape)是一个返回(#Rows,#Cols)元组的属性。

      DataFrame的列数:df.shape[1], len(df.columns)

      df.shape[1]
      # 2
      
      len(df.columns)
      # 2
      

      类似于 len(df.index),len(df.columns) 是这两种方法中速度更快的方法(但需要输入更多字符)。

      系列的行数:

      len(s), s.size, len(s.index)
      
      len(s)
      # 5
      
      s.size
      # 5
      
      len(s.index)
      # 5
      

      s.size 和 len(s.index) 在速度方面大致相同。但我推荐 len(df)。

      size 是一个属性,它返回元素的数量(=任何系列的行数)。 DataFrames 还定义了一个 size 属性,它返回与

      相同的结果
      df.shape[0] * df.shape[1].
      

      非空行数:DataFrame.count 和 Series.count 这里描述的方法只计算非空值(意味着 NaN 被忽略)。

      调用 DataFrame.count 将为每一列返回非 NaN 计数:

      df.count()
      
      A    5
      B    3
      dtype: int64
      For Series, use Series.count to similar effect:
      
      s.count()
      # 3
      

      分组行数:GroupBy.size 对于 DataFrames,使用 DataFrameGroupBy.size 来计算每组的行数。

      df.groupby('A').size()
      
      A
      a    2
      b    2
      c    1
      dtype: int64
      

      同样,对于 Series,您将使用 SeriesGroupBy.size。

      s.groupby(df.A).size()
      
      A
      a    2
      b    2
      c    1
      Name: B, dtype: int64
      

      在这两种情况下,都会返回一个系列。

      分组非空行数:GroupBy.count 与上面类似,但使用 GroupBy.count,而不是 GroupBy.size。请注意,size 总是返回一个 Series,而 count 如果在特定列上调用则返回一个 Series,否则返回一个 DataFrame。

      以下方法返回相同的东西:

      df.groupby('A')['B'].size()
      df.groupby('A').size()
      
      A
      a    2
      b    2
      c    1
      Name: B, dtype: int64
      
      
      
      df.groupby('A').count()
      
         B
      A
      a  2
      b  1
      c  0
      
      
      
      df.groupby('A')['B'].count()
      
      A
      a    2
      b    1
      c    0
      Name: B, dtype: int64
      

      【讨论】:

        【解决方案3】:

        有一种巧妙的方法可以通过聚合和使用 pandas 方法来做到这一点。可以理解为“按行聚合 (axis=1),其中 x 大于或等于 10 且小于或等于 100”。

        df.agg(lambda x : (x.ge(10) & x.le(100)).sum(), axis=1)
        

        【讨论】:

          【解决方案4】:

          这样的事情会帮助你。

          df["n_values_in_range"] = df.apply(
              func=lambda row: count_values_in_range(row, range_min, range_max), axis=1)
          

          【讨论】:

            【解决方案5】:

            试试这个:

            df.apply(lambda x: x.between(10, 100), axis=1).sum(axis=1)
            

            输出:

            0    1
            1    1
            2    1
            3    3
            4    2
            5    2
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-03-11
              • 2020-11-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多