Проверка CSV на наличие аналогичного значения в Python - PullRequest
1 голос
/ 14 февраля 2020

Рассмотрим следующий 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

Я хотел бы сделать следующее:

  • Итерация по всем строкам
  • Итого amount s строк с одинаковым description
  • Возвращает последнюю строку с новым вычисленным amount

Применительно к приведенному выше примеру CSV будет выглядеть вот так:

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

До сих пор я пытался вложить csv.reader() s друг в друга, и я не получаю желаемый результат.

Я бы хотел чтобы достичь этого без каких-либо библиотек и / или модулей.

Вот код, который у меня есть, где 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])

Ответы [ 4 ]

2 голосов
/ 14 февраля 2020

Это будет работать:

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]}')

Я знаю, что вы просили решение без pandas, но вы сэкономите много времени, если будете его использовать:

df = pd.read_csv(report_file)

totals = df.groupby(df['description']).sum()
print(totals)
0 голосов
/ 14 февраля 2020

Вы также можете использовать itertools.groupby и sum() для этого, если не возражаете против вывода в отсортированном виде.

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

Вывод:

17/02/2020,april contract,240.0
16/02/2020,march contract,51.0
0 голосов
/ 14 февраля 2020

Работа со словарем облегчает доступ к значениям

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])

Здесь ваш _dict будет содержать уникальное описание и значения

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

преобразовать в список и добавить заголовки

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]]

сохранить список в csv

with open("out.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(headings)
0 голосов
/ 14 февраля 2020

Я предлагаю вам использовать pandas, это будет эффективно.

или, если вы все еще хотите go, то это поможет.

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]}")

Вывод:

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

Отметьте это как ответ, если вам это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...