在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
我知道你如何制作垃圾箱,但时间戳给我带来了麻烦。 有人可以帮我这个吗? 已经谢谢你了!
答案 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]
希望任何人都觉得它有用。