我的程序必须比较当天/日期的日期和打印总和。 日期将始终按升序排列。
文件:
09/12/2015|9380.0
09/12/2015|7667.0
10/12/2015|3190.0
14/12/2015|3190.0
14/12/2015|5940.0
结果:
09/12/2015 -> 17047.0
10/12/2015 -> 3190.0
14/12/2015 -> 9130.0
这是我的程序
start = "09/12/2015"
end = "14/12/2015"
startstart = datetime.strptime(start, "%d/%m/%Y")
endend = datetime.strptime(end,"%d/%m/%Y")
with open("fileName.txt", "r") as report:
allData = csv.reader(report, delimiter = "|")
for line in allData:
dataLine = datetime.strptime(line[0], "%d/%m/%Y")
if dataLine >= startstart and dataLine <= endend :
print("{0} -> {1}|".format(line[0], line[1]))
我的结果现在有了这个程序:
09/12/2015 -> 9380.0
09/12/2015 -> 7667.0
10/12/2015 -> 3190.0
14/12/2015 -> 3190.0
14/12/2015 -> 5940.0
问题是我打印每个日期和价格,我需要为该日期制作一个日期和所有价格的总和。
答案 0 :(得分:1)
import csv
from datetime import strptime
from itertools import groupby
# this could also be written as
# get_day = lambda row: row[0]
# or as
# from operator import itemgetter # thanks to @ShadowRanger!
# get_day = itemgetter(0)
def get_day(row):
return row[0]
def get_date(s):
return strptime(s, "%d/%m/%Y")
start = get_date("09/12/2015")
end = get_date("14/12/2015")
with open("filename.csv", newline='') as inf:
rows = csv.reader(inf, delimiter='|')
for day, day_rows in groupby(rows, get_day):
if start <= get_date(day) <= end:
day_total = sum(float(v) for d,v in day_rows)
print("{} -> {}".format(day, day_total))
(在给定的输入上)产生
09/12/2015 -> 17047.0
10/12/2015 -> 3190.0
14/12/2015 -> 9130.0
根据需要。
编辑: lambda是一种创建无名函数的方法,它返回单个值; fn = lambda x: x[0]
与
def fn(x):
return x[0]
我把它重写为一个单独的函数而不是lambda ;-)希望有所帮助。
此示例中的 Edit2: groupby
需要
[
('09/12/2015', '9380.0'),
('09/12/2015', '7667.0'),
('10/12/2015', '3190.0'),
('14/12/2015', '3190.0'),
('14/12/2015', '5940.0')
]
并将其转换为
[
('09/12/2015', [('09/12/2015', '9380.0'), ('09/12/2015', '7667.0')]),
('10/12/2015', [('10/12/2015', '3190.0'),]),
('14/12/2015', [('14/12/2015', '3190.0'), ('14/12/2015', '5940.0')])
]
(即每天的子列表)。然后,您可以轻松获取每日小计(这是day_total = sum(...)
行正在执行的操作)。
编辑3:我已在开始日期和结束日期检查中添加。
答案 1 :(得分:1)
我建议使用collections.defaultdict()
对数字求和,然后使用sorted()
保持以下顺序:
from datetime import datetime
from collections import defaultdict
start = "09/12/2015"
end = "14/12/2015"
start = datetime.strptime(start, "%d/%m/%Y")
end = datetime.strptime(end, "%d/%m/%Y")
d = defaultdict(float)
with open('file') as f:
l = [i.split('|') for i in f.read().splitlines()]
for key, value in l:
d[key] += float(value)
l = sorted(((key, value) for (key, value) in d.items()
if datetime.strptime(key, "%d/%m/%Y") >= start and
datetime.strptime(key, "%d/%m/%Y") <= end),
key=lambda x: datetime.strptime(x[0], "%d/%m/%Y"))
for key, value in l:
print('{} -> {}'.format(key, value))
但是,由于您希望保持订单,我还建议您使用collections.OrderedDict()
。这是另一个例子,可能比上面的更简单:
from datetime import datetime
from collections import OrderedDict
start = "09/12/2015"
end = "14/12/2015"
start = datetime.strptime(start, "%d/%m/%Y")
end = datetime.strptime(end, "%d/%m/%Y")
with open('file') as f:
l = [i.split('|') for i in f.read().splitlines()]
d = OrderedDict()
for key, value in l:
date = datetime.strptime(key, "%d/%m/%Y")
if date >= start and date <= end:
try:
d[key] += float(value)
except KeyError:
d[key] = float(value)
for key, value in d.items():
print('{} -> {}'.format(key, value))
演示:
09/12/2015 -> 17047.0
10/12/2015 -> 3190.0
14/12/2015 -> 9130.0
答案 2 :(得分:1)
您不需要转换为日期时间,只需使用OrderedDict进行分组和求和:
from collections import OrderedDict
import csv
with open("in.csv") as f:
od = OrderedDict()
# dte = date string, f = number
for dte, f in csv.reader(f,delimiter="|"):
# cast to float
f = float(f)
# if we have not seen the key before,
# it will get added with default value of 0
od.setdefault(dte, 0)
# access by key/date and add to value
od[dte] += f
for t in od.items():
print("{} ---> {}".format(*t))
输出:
09/12/2015 ---> 17047.0
10/12/2015 ---> 3190.0
14/12/2015 ---> 9130.0
如果您想查找特定日期,可以使用日期字符串进行访问。
print(od[start])
17047.0
答案 3 :(得分:0)
只需将数据读入列表,最终看起来像这样:
data = [[date_1, price_1], [date_2, price_2], ..., [date_n, price_n]]
然后使用这段代码:
from operator import itemgetter
prices = {}
for entry in data:
try:
prices[entry[0]] += entry[1]
except KeyError:
prices[entry[0]] = entry[1]
sorted_prices = sorted(prices.items(), key=itemgetter(0))
我还没有对此进行测试,但这是正确的想法。根据您使用的数据量,您可能希望使用一种解决方案来保持数据的分类。这需要大量数据。在这种情况下,您可以使用OrderedDict
库中的collections
。
答案 4 :(得分:0)
我发现使用dict来积累价格更容易理解,但是你可能不同意:
import csv
from datetime import datetime
#read in data
with open('filename.csv', 'r') as report:
alldata = [row for row in
csv.reader(report, delimiter = "|")]
#define a dict to store each date (as key) and price (as value)
datePrice = {}
#use dict.get function to accumulate price
for row in alldata:
dateKey = datetime.strptime(row[0], "%d/%m/%Y")
datePrice[dateKey] = datePrice.get(dateKey, 0) + float(row[1])
#make a sorted list of keys and iterate through the list
for date in sorted(datePrice):
print("{0} -> {1}".format(datetime.strftime(date, "%d/%m/%Y")
, datePrice[date]))
这是输出:
>09/12/2015 -> 17047.0
>10/12/2015 -> 3190.0
>14/12/2015 -> 9130.0