【问题标题】:Checking a CSV for the existence of a similar value in Python检查 CSV 在 Python 中是否存在类似的值
【发布时间】:2020-02-14 05:47:31
【问题描述】:

考虑以下 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

我想做的是:

  • 遍历所有行
  • 总计amounts 具有相同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])

【问题讨论】:

  • 什么是 csv 对于 4 月合约也有多行?在那种情况下,你想要什么?仅三月还是仅四月?
  • 嗯,cvs 模块是正确的起点。您能否向我们展示一些代码并确切告诉我们它是如何不符合您的要求的?
  • 我编辑了我的问题以表明我希望将相同的效果应用于其中的所有各种合同
  • 你会用熊猫吗?
  • 用代码编辑了我的问题

标签: python loops csv iterator


【解决方案1】:

这将起作用:

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)

【讨论】:

    【解决方案2】:

    我建议你应该使用pandas,它会很有效。

    或者,如果您仍想按照自己的方式行事,那么这将有所帮助。

    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
    

    如果对您有帮助,请将其标记为答案。

    【讨论】:

      【解决方案3】:

      使用字典可以轻松访问值

      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)
      

      【讨论】:

        【解决方案4】:

        如果您不介意以排序形式输出,也可以使用 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
        

        输出:

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

        【讨论】:

          猜你喜欢
          • 2021-11-15
          • 2016-11-05
          • 1970-01-01
          • 2015-02-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-24
          相关资源
          最近更新 更多