在Python中每小时生成多个CSV文件
我有一个叫做 HourlyCsvGeneration.py 的 Python 模块。我有一些数据是每小时生成一次,这些数据保存在 sample.txt 文件里。下面是 sample.txt 中数据的一个示例:
2014-07-24 15:00:00,1,1,1,1,1001
2014-07-24 15:01:00,1,1,1,1,1001
2014-07-24 15:02:00,1,1,1,1,1001
2014-07-24 15:15:00,1,1,1,1,1001
2014-07-24 15:16:00,1,1,1,1,1001
2014-07-24 15:17:00,1,1,1,1,1001
2014-07-24 15:30:00,1,1,1,1,1001
2014-07-24 15:31:00,1,1,1,1,1001
2014-07-24 15:32:00,1,1,1,1,1001
2014-07-24 15:45:00,1,1,1,1,1001
2014-07-24 15:46:00,1,1,1,1,1001
2014-07-24 15:47:00,1,1,1,1,1001
从上面可以看到,有四个时间段:00-15、15-30、30-45 和 45-59,接下来就是下一个小时,依此类推。我正在写代码,读取这个文本文件中的数据,并为一天中的每个小时生成四个 CSV 文件。根据上面的数据,这四个 CSV 文件的命名规则应该是这样的:2014-07-24 15:00.csv,里面包含15:00到15:15之间的数据;2014-07-24 15:15.csv,里面包含15:15到15:30之间的数据,依此类推,每个小时都这样。这个 Python 代码需要处理所有这些事情。
这是我目前的代码片段:
import csv
def connection():
fo = open("sample.txt", "r")
data = fo.readlines()
header = ['tech', 'band', 'region', 'market', 'code']
for line in data:
line = line.strip("\n")
line = line.split(",")
time = line[0]
lines = [x for x in time.split(':') if x]
i = len(lines)
if i == 0:
continue
else:
hour, minute, sec = lines[0], lines[1], lines[2]
minute = int(minute)
if minute >= 0 and minute < 15:
print hour, minute
print line[1:]
elif minute >= 15 and minute < 30:
print hour, minute
print line[1:]
elif minute >= 30 and minute < 45:
print hour, minute
print line[1:]
elif minute >=45 and minute < 59:
print hour, minute
print line[1:]
connection()
[1:] 可以给出每个时间段的正确数据,但我在生成 CSV 文件和写入数据时遇到了困难。所以我想把 [1:] 的内容写入对应时间段的 CSV 文件中,并按照上面描述的命名规则来命名。
期望的输出是:
2014-07-24 15:00.csv must contain
1,1,1,1,1001
1,1,1,1,1001
1,1,1,1,1001
2014-07-24 15:15.csv must contain
1,1,1,1,1001
1,1,1,1,1001
1,1,1,1,1001
这样对于 15:30.csv 和 15:45.csv 也是一样。请记住,这只是一个小数据块。实际的数据是每小时都有的。这意味着每个小时生成四个 CSV 文件,也就是一天要生成 24*4 个文件。那么我该如何让我的代码更健壮和高效呢?
有什么帮助吗?谢谢!
4 个回答
我建议你使用pandas来处理这个问题。它可以帮你处理很多繁琐的工作。
import pandas as pd
df = pd.read_table('DummyText.txt',sep=',',index_col=0,parse_dates=True,header=None)
fname = (str(pd.datetime(2014,7,24,15,0))+'.csv').replace(':','-')
df[pd.datetime(2014,7,24,15,0):pd.datetime(2014,7,24,15,15)].to_csv(fname,header=None)
我把文件名中的:
去掉了,因为它似乎不喜欢这个符号。你只需要设置一些循环来遍历日期和时间就可以了。
这里有一些可能对你有帮助的方法
import csv
from datetime import datetime
def get_higher_minute(minute_of_day):
return (((minute_of_day/ 15) + 1 ) % 4) * 15
def connection():
import csv
with open('some.csv', 'rb') as f:
reader = csv.reader(f)
for row in reader:
dateObject = datetime.strptime(row[0], '%Y-%m-%d %H:%M:%S')
minute_of_day = dateObject.minute
higher_minute = get_higher_minute(minute_of_day)
newdate = dateObject.replace(minute = higher_minute)
file_name_of_new_csv = "%s.csv" % dateObject.strftime("%Y-%m-%d %H:%M")
new_csv_writer = csv.writer(file_name_of_new_csv, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL)
new_csv_writer.writerow(row[0:])
new_csv_writer.close()
def main():
connection()
if __name__=="__main__":
main()
希望这些能帮到你
抱歉,我忘记关闭 new_csv_writer 了。
你的问题并不简单,因为如果你试图一次性打开所有的输出文件,你会用完文件描述符,导致程序崩溃。所以你应该做的是以追加模式打开一个文件,写入一行内容,然后关闭这个文件。这种操作效率不是特别高,所以现在不需要太担心效率的问题。
outfile = open("2014-07-24 15:00.csv","a")
outfile.write("csv, line, data\n")
outfile.close()
看起来这个问题可以用 itertools.groupby
来解决,前提是时间戳的值是严格递增的:
from datetime import datetime as DateTime
from itertools import imap, groupby
from operator import itemgetter
get_first = itemgetter(0)
get_second = itemgetter(1)
def process_line(line):
timestamp_string, _, values = line.partition(',')
timestamp = DateTime.strptime(timestamp_string, '%Y-%m-%d %H:%M:%S')
return (
timestamp.replace(minute=timestamp.minute // 15 * 15, second=0),
values
)
def main():
with open('sample.txt', 'r') as lines:
for date, group in groupby(imap(process_line, lines), get_first):
with open('{0:%Y-%m-%d %H_%M}.csv'.format(date), 'w') as out_file:
out_file.writelines(imap(get_second, group))
if __name__ == '__main__':
main()