简体   繁体   English

在 Python 中检查 CSV 中是否存在类似的值

[英]Checking a CSV for the existence of a similar value in Python

Consider the following CSV:考虑以下 CSV:

date,description,amount
14/02/2020,march contract,-99.00
15/02/2020,april contract,340.00
16/02/2020,march contract,150.00
17/02/2020,april contract,-100.00

What I'd like to do is:我想做的是:

  • Iterate through all of the rows遍历所有行
  • Total the amount s of lines which have the same description合计amount S的具有相同的线的description
  • Return the last line which has that newly-calculated amount返回具有新计算amount的最后一行

Applied to the above example, the CSV would look like this:应用于上述示例,CSV 将如下所示:

16/02/2020,march contract,51.00
17/02/2020,april contract,240.00

So far, I've tried nesting csv.reader() s inside of each other and I'm not getting the result I am wanting.到目前为止,我已经尝试在彼此内部嵌套csv.reader() ,但没有得到我想要的结果。

I'd like to achieve this without any libraries and/or modules.我想在没有任何库和/或模块的情况下实现这一点。

Here is the code I have so far, where first_row is each row in the CSV and second_row is the iteration of looking for matching descriptions:这是我到目前为止的代码,其中first_row是 CSV 中的每一行,而second_row是寻找匹配描述的迭代:

csv_reader = csv.reader(report_file)
        for first_row in csv_reader:
            description_index = 5
            amount_index = 13
            print(first_row)
            for second_row in csv_reader:
                if second_row is not first_row:
                    print(first_row[description_index] == second_row[description_index])
                        if first_row[description_index] == second_row[description_index]:
                            first_row[amount_index] = float(first_row[amount_index]) + float(second_row[amount_index])

This will work:这将起作用:

import csv
uniques = {}  # dictionary to store key/value pairs


with open(report_file, newline='') as f:
    reader = csv.reader(f, delimiter=',')
    next(reader, None)  # skip header row
    for data in reader:
        date = data[0]
        description = data[1]
        if description in uniques:
            cumulative_total = uniques[description][0]
            uniques[description] = [cumulative_total+float(data[2]), date]
        else:
            uniques[description] = [float(data[2]), date]

# print output
for desc, val in uniques.items():
    print(f'{val[0]}, {desc}, {val[1]}')

I know that you've asked for a solution without pandas, but you'll save yourself a lot of time if you use it:我知道您已经要求没有 Pandas 的解决方案,但是如果您使用它,您会节省很多时间:

df = pd.read_csv(report_file)

totals = df.groupby(df['description']).sum()
print(totals)

I suggest you should use pandas , it'll be efficient.我建议你应该使用pandas ,它会很有效率。

or if you still want to go with your way then this will help.或者如果您仍然想按照自己的方式行事,那么这将有所帮助。

import csv

with open('mycsv.csv') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    value_dict = {}
    line_no = 0
    for row in csv_reader:
        if line_no == 0:
            line_no += 1
            continue
        cur_date = row[0]
        cur_mon = row[1]
        cur_val = float(row[2])
        if row[1] not in value_dict.keys():
            value_dict[cur_mon] = [cur_date, cur_val]
        else:
            old_date, old_val = value_dict[cur_mon]
            value_dict[cur_mon] = [cur_date, (old_val + cur_val)]
        line_no += 1

for key, val_list in value_dict.items():
    print(f"{val_list[0]},{key},{val_list[1]}")

Output:输出:

16/02/2020,march contract,51.0
17/02/2020,april contract,240.0

Mark this as answer if it helps you.如果对您有帮助,请将其标记为答案。

working with dictionary makes it easy to access values使用字典可以轻松访问值

import csv
from datetime import datetime

_dict = {}
with open("test.csv", "r") as f:
    reader = csv.reader(f, delimiter=",")

    for i, line in enumerate(reader):
        if i==0:
            headings = [line]
        else:
            if _dict.get(line[1],None) is None:
                _dict[line[1]] = {
                                    'date':line[0], 
                                    'amount':float(line[2])
                                 }
            else:
                if datetime.strptime(_dict.get(line[1]).get('date'),'%d/%m/%Y') < datetime.strptime(line[0],'%d/%m/%Y'):
                    _dict[line[1]]['date'] = line[0]

                _dict[line[1]]['amount'] = _dict[line[1]]['amount'] + float(line[2])

Here your _dict will contain unique description and values在这里,您的_dict将包含唯一的描述和值

>>> print(_dict)
{'march contract': {'date': '16/02/2020', 'amount': 51.0},  
'april contract': {'date': '17/02/2020', 'amount': 240.0}}

convert to list and add headings转换为列表并添加标题

headings.extend([[value['date'],key,value['amount']] for key,value in _dict.items()])

>>>print(headings)
[['date', 'description', 'amount'],['16/02/2020', 'march contract', 51.0], ['17/02/2020', 'april contract', 240.0]]

save list to csv将列表保存到 csv

with open("out.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(headings)

You can also use itertools.groupby and sum() for this if you don't mind outputting in sorted form.如果你不介意以排序的形式输出,你也可以使用itertools.groupbysum()

from datetime import datetime
from itertools import groupby
import csv

with open(report_file, 'r') as f:
    reader = csv.reader(f)
    lst = list(reader)[1:]

    sorted_input = sorted(lst, key=lambda x : (x[1], datetime.strptime(x[0],'%d/%m/%Y')))  #sort by description and date
    groups = groupby(sorted_input, key=lambda x : x[1])
    for k,g in groups:
        rows = list(g) 
        total = sum(float(row[2]) for row in rows)
        print(f'{rows[-1][0]},{k},{total}')  #print last date, description, total

Output:输出:

17/02/2020,april contract,240.0
16/02/2020,march contract,51.0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM