使用python中的日期创建一个bin列

时间:2015-05-10 12:42:46

标签: python-2.7 datetime time bins

在python中,我的数据看起来像500.000行:

时间计数

1-1-1900 10:41:00 1

3-1-1900 09:54:00 1

4-1-1900 15:45:00 1

5-1-1900 18:41:00 1

4-1-1900 15:45:00 1

我希望在这样的四分之一区域中创建一个带有分档的新列:

bins count

9:00-9:15 2

9:15-9:30 4

9:30-9:45 4

10:00-10:15 4

我知道你如何制作垃圾箱,但时间戳给我带来了麻烦。 有人可以帮我这个吗? 已经谢谢你了!

2 个答案:

答案 0 :(得分:1)

嗯,我不确定这是你要的。如果不是,我会建议您改进您的问题,因为您很难理解您的问题。特别是,看到你已经尝试过的事情会很高兴。

from __future__ import division, print_function
from collections import namedtuple
from itertools import product
from datetime import time
from StringIO import StringIO


MAX_HOURS = 23
MAX_MINUTES = 59


def process_data_file(data_file):
    """
    The data_file is supposed to be an opened file object
    """
    time_entry = namedtuple("time_entry", ["time", "count"])
    data_to_bin = []
    for line in data_file:
        t, count = line.rstrip().split("\t")
        t = map(int, t.split()[-1].split(":")[:2])
        data_to_bin.append(time_entry(time(*t), int(count)))
    return data_to_bin


def make_milestones(min_hour=0, max_hour=MAX_HOURS, interval=15):
    minutes = [minutes for minutes in xrange(MAX_MINUTES+1) if not minutes % interval]
    hours = range(min_hour, max_hour+1)
    return [time(*milestone) for milestone in list(product(hours, minutes))]


def bin_time(data_to_bin, milestones):
    time_entry = namedtuple("time_entry", ["time", "count"])
    data_to_bin = sorted(data_to_bin, key=lambda time_entry: time_entry.time, reverse=True)
    binned_data = []
    current_count = 0
    upper = milestones.pop()
    lower = milestones.pop()
    for entry in data_to_bin:
        while not lower <= entry.time <= upper:
            if current_count:
                binned_data.append(time_entry("{}-{}".format(str(lower)[:-3], str(upper)[:-3]), current_count))
                current_count = 0
            upper, lower = lower, milestones.pop()
        current_count += entry.count
    return binned_data


data_file = StringIO("""1-1-1900 10:41:00\t1
3-1-1900 09:54:00\t1
4-1-1900 15:45:00\t1
5-1-1900 18:41:00\t1
4-1-1900 15:45:00\t1""")


binned_time = bin_time(process_data_file(data_file), make_milestones())
for entry in binned_time:
    print(entry.time, entry.count, sep="\t")

输出:

18:30-18:45 1
15:45-16:00 2
10:30-10:45 1

答案 1 :(得分:0)

我知道已经晚了。但是迟到总比不到好。我也遇到了类似的要求,并使用pandas

  • 首先,在pandas数据框中加载数据

  • 第二,检查TIME列必须是datetime对象,而不是对象类型(如字符串或其他类型)。您可以通过

    进行检查

    df.info()

例如,在我的情况下,TIME列最初是对象类型,即字符串类型

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 17640 entries, 0 to 17639
Data columns (total 3 columns):
TIME           17640 non-null object
value          17640 non-null int64
dtypes: int64(1), object(2)
memory usage: 413.5+ KB
  • 在这种情况下,请使用此命令将其转换为pandas datetime对象

    df['TIME'] = pd.to_datetime(df['TIME']) 如果它已经是日期时间格式,则忽略它

    df.info()现在提供了更新的格式

 <class 'pandas.core.frame.DataFrame'>
 RangeIndex: 17640 entries, 0 to 17639
 Data columns (total 3 columns):
 TIME           17640 non-null datetime64[ns]
 value          17640 non-null int64
 dtypes: datetime64[ns](2), int64(1)
 memory usage: 413.5 KB
  • 现在我们的数据框已经可以魔术了:)

     
      counts = pd.Series(index=df.TIME, data=np.array(df.count)).resample('15T').count()
      print(counts[:3])
    
    TIME
    2017-07-01 00:00:00    3
    2017-07-01 00:15:00    3
    2017-07-01 00:30:00    3
    Freq: 15T, dtype: int64
    
    上面命令15T中的

    表示15分钟的存储桶,您可以将其替换为D表示日存储桶,2D表示2天存储桶,M表示月份存储桶,{{ 1}} 2个月的存储桶,依此类推。您可以在此link

  • 上阅读这些符号的详细信息
  • 现在,如上所示,我们的存储桶数据已完成。对于时间范围,请使用此命令。使用与数据相同的时间范围。就我而言,我的数据是3个月,因此我要创建3个月的时间范围。

2M
 r = pd.date_range('2017-07', '2017-09', freq='15T')
 x = np.repeat(np.array(r), 2, axis=0)[1:-1]
 # now reshape data to fit in Dataframe
 x = np.array(x)[:].reshape(-1, 2)
 # now fit in dataframe and print it
 final_df = pd.DataFrame(x, columns=['start', 'end'])
 print(final_df[:3])

日期范围也已完成

  • 现在追加计数和日期范围以获取最终结果

                      start                 end
    0   2017-07-01 00:00:00 2017-07-01 00:15:00
    1   2017-07-01 00:15:00 2017-07-01 00:30:00
    2   2017-07-01 00:30:00 2017-07-01 00:45:00
    
final_df['count'] = np.array(means)
print(final_df[:3]

希望任何人都觉得它有用。