使用 Python 进行每小时频率计数

Posted

技术标签:

【中文标题】使用 Python 进行每小时频率计数【英文标题】:Hourly frequency count with Python 【发布时间】:2014-01-16 04:01:28 【问题描述】:

我有这个每小时的 csv 数据按天按天排序数百天:

2011.05.16,00:00,1.40893 2011.05.16,01:00,1.40760 2011.05.16,02:00,1.40750 2011.05.16,03:00,1.40649

我想计算每小时设置每日最大值的次数,所以如果在 00:00 我的最大值为 2011.05.16 天,我将 1 添加到 00:00 和以此类推。 为此,我使用循环来计算小时数,例如索引:

def graph():    
Date, Time,  High = np.genfromtxt(myPath, delimiter=",",
                                  unpack = True,  converters=0:date_converter)                                                                           
numList = [""] * 24
index=0
hour=0    
count = [0] * 24

for eachHour in Time:        
    numList[hour] += str(High[index])        
    index += 1
    hour +=1        

    if hour == 24:           
        higher = (numList.index(max(numList)))
        count[higher] += 1            
        hour = 0            
        numList = [""] * 24

问题是,在我的数据中,通常会出现一些小时缺失的间隙,但循环无法识别它并继续将值放入下一小时索引中。我到处搜索,但我是编程新手,这是我的第一个“复杂”工作,所以我需要更具体的答案来了解我的案例是如何工作的。 那么如何按照解释的方式计算每小时频率? 最终结果应该是这样的:

00:00 n time max of the day   
01:00 n time max of the day   
02:00 n time max of the day  
etc

【问题讨论】:

您已将pandas 添加为标签,但您似乎并未使用它。基于pandas 的解决方案是否可以接受? 当然可以接受任何解决方案。 “当日最高值”是指“当天曾经的最高值,即每日最高值”,还是“一个新的已设置最大值”? 哇!对不起,伙计们,我没想到会在这里有这么多参与 :) 我的意思是每日最大值,而不是有史以来的最高值。例如,每次一天的最高值在 15:00 时,在 15:00 时添加 1 个计数。现在我需要一些时间来检查所有这些答案,谢谢大家! 【参考方案1】:

先读入csv:

In [11]: df = pd.read_csv('foo.csv', sep=',', header=None, parse_dates=[[0, 1]])

In [12]: df.columns = ['date', 'val']

In [13]: df.set_index('date', inplace=True)

In [14]: df
Out[14]: 
                         val
date                        
2011-05-16 00:00:00  1.40893
2011-05-16 01:00:00  1.40760
2011-05-16 02:00:00  1.40750
2011-05-16 03:00:00  1.40649

使用 resample 获得每天的最大值:

In [15]: day_max = df.resample('D', how='max')

检查每个值是否为day max:

In [16]: df['is_day_max'] = day_max.lookup(df.index.normalize(), len(df) * ['val']) == df.val

In [17]: df
Out[17]: 
                         val is_day_max
date                                   
2011-05-16 00:00:00  1.40893       True
2011-05-16 01:00:00  1.40760      False
2011-05-16 02:00:00  1.40750      False
2011-05-16 03:00:00  1.40649      False

然后在每个小时内总结这些:

In [18]: df.groupby(df.index.time)['is_day_max'].sum()
Out[18]: 
00:00:00    1
01:00:00    0
02:00:00    0
03:00:00    0
Name: is_day_max, dtype: float64

【讨论】:

嗯。在二读时,我认为您是对的,并且 OP 正在寻找每日最大值,而不仅仅是设置新的最大值。 :-/ @DSm 虽然 cummax kindof 更有意义(会有更多 Trues) @AndyHayden 我认为你的最后一步(按小时重新采样)不是他所要求的。顺便说一句,如果不是所有时间都可用,这将产生错误('无法将 NA 转换为整数') 我回答的最后一步是这样做的 (df.groupby(df.index.time)['daily_max'].sum()) @AndyHayden 我编辑了您的答案,因为它不正确(据我所知)。我希望这没问题。【参考方案2】:

使用 pandas 的解决方案:假设您有一个日期为索引的数据框,您可以先添加一列来表示每天的最大值,然后按小时分组并对出现次数求和:

In [32]: df['daily_max'] = df.groupby(df.index.date).transform(lambda x: x==x.max())
In [33]: df
Out[33]: 
                       value daily_max
date_time                             
2011-05-16 00:00:00  1.40893      True
2011-05-16 01:00:00  1.40760     False
2011-05-16 02:00:00  1.40750     False
2011-05-16 03:00:00  1.40649     False
2011-05-17 02:00:00  1.40893      True
2011-05-17 03:00:00  1.40760     False
2011-05-17 04:00:00  1.40750     False
2011-05-17 05:00:00  1.40649     False
2011-05-18 02:00:00  1.40893      True
2011-05-18 03:00:00  1.40760     False
2011-05-18 04:00:00  1.40750     False
2011-05-18 05:00:00  1.40649     False

In [34]: df.groupby(df.index.time)['daily_max'].sum()
Out[34]: 
00:00:00    1
01:00:00    0
02:00:00    2
03:00:00    0
04:00:00    0
05:00:00    0
Name: daily_max, dtype: float64

对于较旧的 pandas 版本,这将给出与上述相同的结果(假设您的 df 具有 DatetimeIndex):

df['date'] = [t.date() for t in df.index.to_pydatetime()]
df['time'] = [t.time() for t in df.index.to_pydatetime()]
df['daily_max'] = df.groupby('date')['value'].transform(lambda x: x==x.max())
df.groupby('time')['daily_max'].sum()

我在这个例子中使用的数据框:

from StringIO import StringIO

s="""2011.05.16,00:00,1.40893
2011.05.16,01:00,1.40760
2011.05.16,02:00,1.40750
2011.05.16,03:00,1.40649
2011.05.17,02:00,1.40893
2011.05.17,03:00,1.40760
2011.05.17,04:00,1.40750
2011.05.17,05:00,1.40649
2011.05.18,02:00,1.40893
2011.05.18,03:00,1.40760
2011.05.18,04:00,1.40750
2011.05.18,05:00,1.40649"""

df = pd.read_csv(StringIO(s), header=None, names=['date', 'time', 'value'], parse_dates=[['date', 'time']])
df = df.set_index('date_time')

【讨论】:

我试过这个,但它给了我这个错误:df['daily_max'] = df.groupby(df.index.date).transform(lambda x: x==x.max ()) AttributeError: 'Index' 对象没有属性 'date' 这意味着您的索引不是 DatetimeIndex。您是否阅读了我在答案中显示的数据?否则,您也可以尝试df.index = pd.to_datetime(df.index) 将字符串转换为日期时间。 或者,这也可能意味着您有一个较旧的 pandas 版本,其中 date 属性尚不可用于 DatetimeIndex。我添加了一个可以与旧版 pandas 一起使用的版本,尽管我建议尝试更新。 大声笑将您的答案和其他答案结合起来!非常感谢您的帮助! 我的答案的第一部分不起作用吗? (只是出于好奇)【参考方案3】:

我不确定您要计算的确切内容,但这是我计算数据集中值的方法

from time import strptime,strftime

time_format="%H:%M"
date_format="%Y.%m.%d"

def date_values(flo):
    for line in flo:
        try:
            date_str, time_str, value = line.split(',')
            date = strptime(date_str,"%Y.%m.%d")
            time = strptime(time_str,"%H:%M")
            value = float(value)
            yield (date, time, value)
        except ValueError:
            pass

def day_values(flo):
    days = 
    for date,time,value in date_values(flo):
        try:
            days[date].append(value)
        except KeyError:
            days[date] = [ value ]

    return days

if __name__ == '__main__':
    from sys import stdin

    for day,values in day_values(stdin).items():
        print("0: 1 (max of 2)".format(
              strftime(date_format, day),
              values, 
              max(values)))

date_values 函数将返回一个生成器,该生成器会遍历数据输入的有效行。 day_values 函数使用生成器构造一个字典,其中键是日期,值是该日期的值数组。根据您的描述,我不确定时间如何发挥作用,如果您可以澄清或提供更大的数据集以及您希望看到的结果示例,我可以对此进行扩展。

如果我将该文件命名为freq_count.py 并假设您的数据集在一个名为 data 的文件中,我会得到

$ python freq_count.py < data
2011.05.16: [1.40893, 1.4076, 1.4075, 1.40649] (max of 1.40893)

统计最大值出现的频率:

def count_freq(values):
    return len( [ v for v in values if v == max(values) ] ) 

使用列表推导生成一个列表,其中包含values 输入中的所有最大值,然后获取结果列表的长度。

【讨论】:

以上是关于使用 Python 进行每小时频率计数的主要内容,如果未能解决你的问题,请参考以下文章

Seaborn:带有频率的计数图()

二维列表中的Python计数元素频率[重复]

数据结构与算法之深入解析“推文计数”的求解思路与算法示例

python csv文件频率计数

频率计和通用计数器的区别?

Python中的项目频率计数