【问题标题】:How to loop through mismatched data如何遍历不匹配的数据
【发布时间】:2018-03-21 06:53:50
【问题描述】:

所以我一直在想这怎么可能,但什么都没有想到。

我有 2 个包含日期和数据的 csv 文件。然而,日期不匹配。我希望能够编写一个代码,允许我遍历所有数据,找到匹配的日期,然后创建一个文本文档,其中包含共同的日期和来自单独工作表的 2 个数据值。另一种选择是自己在excel中匹配它们。

有什么建议吗?

例如。我想要完成的事情:

假设我有这个文件1:

01/01/01 | 1 
01/02/01 | 2 
01/03/01 | 3 
01/04/01 | 4 
01/05/01 | 5 
01/06/01 | 6 
01/07/01 | 7 
01/08/01 | 8 

还有这个文件2:

01/05/01 | 9  
01/06/01 | 22 
01/07/01 | 33 
01/08/01 | 44
01/09/01 | 55
01/10/01 | 66
01/11/01 | 77
01/12/01 | 88

我希望返回的是(运行循环后):

01/05/01 | 5 | 9
01/06/01 | 6 | 22
01/07/01 | 7 | 33
01/08/01 | 8 | 44

任何帮助将不胜感激,谢谢!

【问题讨论】:

    标签: python excel csv date text


    【解决方案1】:
    • 从每个文件中读取第一条记录,r1r2
    • 提取日期 d1d2
    • 虽然两个文件中都有剩余数据:
      • 如果 d1 == d2:
        • 合并记录并打印
        • 获取每个文件的下一行(新的 r1r2
      • 否则如果 d1
      • 获取下一个r1
    • 其他
      • 获取下一个r2

    简而言之,您正在逐步浏览这两个文件,并在每个文件中保留一个“书签”。如果记录匹配,则合并并打印;推进这两个文件。否则,将日期中“落后”的书签前进。

    【讨论】:

      【解决方案2】:

      使用 CSV 模块读取这两个文件,将它们转换为映射date => list[values] 的字典,然后打印它们。

      import csv
      
      # Extract CSV
      csv1 = []
      with open('first.csv', 'r') as f1:
          csv_reader = csv.reader(f1)
          for row in csv_reader:
              csv1.append(row)
      
      csv2 = []
      with open('second.csv', 'r') as f2:
          csv_reader = csv.reader(f2)
          for row in csv_reader:
              csv2.append(row)
      
      # Initialize dict which will map dates to values
      d = {}
      
      # Map dates to values by getting a default array and appending the values
      for row in csv1:
          v = d.get(row[0], [])
          v.append(row[1])
          d[row[0]] = v
      
      for row in csv2:
          v = d.get(row[0], [])
          v.append(row[1])
          d[row[0]] = v
      
      # Print results
      for k, v in d.items():
          values = ' | '.join(list(map(str, v)))
          print(f'{k} | {values}')
      

      【讨论】:

        【解决方案3】:

        我认为 pandas 连接逻辑非常适合这项任务,因为您实际上是在请求按日期键控的内部连接。

        首先为您的日期定义一个解析函数(我添加了它以防您需要将这些视为实际日期以便在 python 中进一步处理)。然后将每个 csv 文件加载到单独的数据框中。最后加入并删除NaN 值以获取您寻求的内部联接(或者通过在join 函数中设置how 参数来明确地进行内部联接)。您还可以使用 to_csv 函数轻松地将输出数据帧放入 csv 文件中。

        如果您希望通过聚合或加入来获得更多创意,那么 pandas 就是您的最佳选择。

        import pandas
        parser = lambda date: pandas.datetime.strptime(date.strip(), '%y/%m/%d')
        dt = pandas.read_csv('H:\\one.csv', parse_dates = [0], date_parser = parser, index_col=0, delimiter="|", names = ["date", "val"])
        dt2 = pandas.read_csv('H:\\two.csv', parse_dates = [0], date_parser = parser, index_col=0, delimiter="|", names = ["date", "val2"])
        dt.join(dt2).dropna().to_csv("H:\\output.csv")
        

        这也可以,但你会失去 python 中所有特定于日期的功能:

        import pandas
        dt = pandas.read_csv('H:\\one.csv', index_col=0, delimiter="|", names = ["date", "val"])
        dt2 = pandas.read_csv('H:\\two.csv', index_col=0, delimiter="|", names = ["date", "val2"])
        dt.join(dt2, how='inner').to_csv("H:\\output.csv")
        

        【讨论】:

          【解决方案4】:

          使用defaultdict 的列表来存储 CSV 文件中的数据,然后在 dict 中查找列表中具有多个值的项目。

          import csv
          from collections import defaultdict
          
          merged = defaultdict(list)
          
          for filename in 'f1.csv', 'f2.csv':
              with open(filename) as f:
                  for date, value in csv.reader(f, delimiter='|'):
                      merged[date].append(value)
          
          with open('out.csv', 'w') as f:
              w = csv.writer(f, delimiter='|')
              for date in sorted(merged):
                  if len(merged[date]) > 1:
                      w.writerow([date] + merged[date])
          

          这将(几乎)生成您需要的文件,唯一的区别是分隔符是单个 | 而不是 |(周围有空格)。我还假设输入文件也有类似的分隔符。

          【讨论】:

            猜你喜欢
            • 2021-03-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-06-14
            • 1970-01-01
            • 2023-03-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多