【问题标题】:Using Python's Pandas to find average values by bins使用 Python 的 Pandas 按 bin 查找平均值
【发布时间】:2014-07-11 16:33:09
【问题描述】:

我刚开始使用 pandas 来分析一段时间内的地下水井数据。

我在文本文件中的数据看起来像 (site_no, date, well_level):

485438103132901 19800417    -7.1

485438103132901 19800506    -6.8

483622101085001 19790910    -6.7

485438103132901 19790731    -6.2

483845101112801 19801111    -5.37

484123101124601 19801111    -5.3

485438103132901 19770706    -4.98

我想要一个按 5 年增量划分的平均井水平和计数的输出:

site_no   avg 1960-end1964  count    avg 1965-end1969  count    avg 1970-end1974 count

我正在读取数据:

names = ['site_no','date','wtr_lvl']
df = pd.read_csv('D:\info.txt', sep='\t',names=names)

我可以通过以下方式找到网站的总体平均值:

avg = df.groupby(['site_no'])['wtr_lvl'].mean().reset_index()

我的原始垃圾箱尝试使用:

a1 = df[df.date > 19600000]
a2 = a1[a1.date < 19650000]
avga2 = a2.groupby(['site_no'])['wtr_lvl'].mean()

我的问题:如何加入结果以根据需要显示?我尝试了合并、连接和追加,但它们不允许空数据框(发生这种情况)。此外,我确信有一种简单的方法可以按日期对数据进行分类。谢谢。

【问题讨论】:

    标签: python pandas bin


    【解决方案1】:

    最简洁的方法可能是将其转换为timeseris 数据,然后对其进行下采样以获得均值:

    In [75]:
    
    print df
                             ID  Level
    1                                 
    1980-04-17  485438103132901  -7.10
    1980-05-06  485438103132901  -6.80
    1979-09-10  483622101085001  -6.70
    1979-07-31  485438103132901  -6.20
    1980-11-11  483845101112801  -5.37
    1980-11-11  484123101124601  -5.30
    1977-07-06  485438103132901  -4.98
    In [76]:
    
    df.Level.resample('60M', how='mean') 
    #also may consider different time alias: '5A', '5BA', '5AS', etc:
    #see: http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
    Out[76]:
    1
    1977-07-31   -4.980
    1982-07-31   -6.245
    Freq: 60M, Name: Level, dtype: float64
    

    或者,您可以将groupbycut 一起使用:

    In [99]:
    
    print df.groupby(pd.cut(df.index.year, pd.date_range('1960', periods=5, freq='5A').year, include_lowest=True)).mean()
                            ID     Level
    [1960, 1965]           NaN       NaN
    (1965, 1970]           NaN       NaN
    (1970, 1975]           NaN       NaN
    (1975, 1980]  4.847632e+14 -6.064286
    

    还有 ID:

    In [100]:
    
    print df.groupby(['ID', 
                      pd.cut(df.index.year, pd.date_range('1960', periods=5, freq='5A').year, include_lowest=True)]).mean()
                                  Level
    ID                                 
    483622101085001 (1975, 1980]  -6.70
    483845101112801 (1975, 1980]  -5.37
    484123101124601 (1975, 1980]  -5.30
    485438103132901 (1975, 1980]  -6.27
    

    【讨论】:

      【解决方案2】:

      所以我喜欢做的是用四舍五入的 bin 编号创建一个单独的列:

          bin_width = 50000
          mult = 1. / bin_width
          df['bin'] = np.floor(ser * mult + .5) / mult
      

      然后,只需按垃圾箱本身分组

          df.groupby('bin').mean()
      

      另外注意,你可以一次做多个真值评估:

          df[(df.date > a) & (df.date < b)]
      

      【讨论】:

      • ser 未在此处定义。我将最后一行更改为完美的: df['bin'] = [ np.trunc( x * mult + mult ) for x in range( len( df ) ) ]
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-30
      • 2019-11-23
      • 1970-01-01
      • 2021-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多