【问题标题】:How to merge multiple csv files into one with unique columns in Rails如何在 Rails 中将多个 csv 文件合并为一个具有唯一列的文件
【发布时间】:2019-08-28 12:11:02
【问题描述】:

我在 S3 中有多个 csv 文件,我想将这些文件合并为一个,并根据列删除重复项。

文件1:

Date            ID     Name                 Count  Price
2019-08-25    110146  Amazon In-App           1    23
2019-08-25    121615  Google US Rally         0    0
2019-08-25    208442  Google Rewarded US      47   12
2019-08-26    110146  Amazon In-App           10   40
2019-08-26    121615  Google US Rally         0    0
2019-08-26    208442  Google Rewarded US      0   0

文件2:

Date            ID     Name                 Count  Price
2019-08-26    110146  Amazon In-App           30    90
2019-08-26    121615  Google US Rally         5    25
2019-08-26    208442  Google Rewarded US      15   45
2019-08-27    110146  Amazon In-App           5    15
2019-08-27    121615  Google US Rally         10    40
2019-08-27    208442  Google Rewarded US      0   0

文件3:

Date            ID     Name                 Count  Price
2019-08-27    110146  Amazon In-App           30    70
2019-08-27    121615  Google US Rally         12    50
2019-08-27    208442  Google Rewarded US      15   45
2019-08-28    110146  Amazon In-App           15    55
2019-08-28    121615  Google US Rally         20    60
2019-08-28    208442  Google Rewarded US      0   0

以下是示例文件。我想将上述文件与 ID 和 Name 等唯一列合并。

我的预期输出:

final_output_file:

Date            ID     Name                 Count  Price
2019-08-25    110146  Amazon In-App           1    23
2019-08-25    121615  Google US Rally         0    0
2019-08-25    208442  Google Rewarded US      47   12
2019-08-26    110146  Amazon In-App           30    90
2019-08-26    121615  Google US Rally         5    25
2019-08-26    208442  Google Rewarded US      15   45
2019-08-27    110146  Amazon In-App           30    70
2019-08-27    121615  Google US Rally         12    50
2019-08-27    208442  Google Rewarded US      15   45
2019-08-28    110146  Amazon In-App           15    55
2019-08-28    121615  Google US Rally         20    60
2019-08-28    208442  Google Rewarded US      0   0

如何使用 ruby​​ 实现?

我尝试了以下方法并匹配了所有列,但它不能满足我的需要。

require 'set'
unique = Set.new
Dir.glob('revenue_report_*.csv') do |f|
  File.foreach(f) { |l| unique << l }
end
File.write('unique.csv', unique.sort.join)

【问题讨论】:

  • 多个文件中是否存在具有相同 ID 的行?文件 1 中的行是否可以与文件 2 中的行具有相同的 ID,但其他列中的值不同?
  • 在给定匹配日期和 ID 的情况下,您使用什么来决定保留哪条记录?例如,给定文件 2 和 3 中 8/27 的 Google US Rally 的计数和价格值,您是否还保留较高的计数和价格值,或者您是否覆盖以使最后处理的文件获胜?是否需要按顺序应用文件,以便将匹配的日期/id 视为更新,还是有其他规则?
  • @Виктор 两个问题都是。
  • 所以你想合并 3 个 csv-s 并且只删除那些所有列都相等的行?
  • 请通过编辑来澄清您的问题,而不是期望读者通过研究 cmets 弄清楚您要做什么。

标签: ruby csv


【解决方案1】:

代码

require 'csv'

def doit(*csv_input_files, csv_output_file)
  CSV.open(csv_output_file, "wb", headers: true) do |csv_out|
    csv_out << CSV.open(csv_input_files.first, &:readline)
    csv_input_files.each_with_object({}) do |f,h|
      CSV.read(f, headers: true).each do |csv|
        h[[csv['Date'], csv['ID']]] = csv
      end
    end.values.each { |row| csv_out << row }
  end
end

示例

F1   = 'f1.csv'
F2   = 'f2.csv'
F3   = 'f3.csv'

File.write(F1, <<~END)
Date,ID,Name,Count,Price
2019-08-25,110146,Amazon In-App,1,23
2019-08-25,121615,Google US Rally,0,0
2019-08-25,208442,Google Rewarded US,47,12
2019-08-26,110146,Amazon In-App,10,40
2019-08-26,121615,Google US Rally,0,0
2019-08-26,208442,Google Rewarded US,0,0
END
  #=> 260

File.write(F2, <<~END)
Date,ID,Name,Count,Price
2019-08-26,110146,Amazon In-App,30,90
2019-08-26,121615,Google US Rally,5,25
2019-08-26,208442,Google Rewarded US,15,45
2019-08-27,110146,Amazon In-App,5,15
2019-08-27,121615,Google US Rally,10,40
2019-08-27,208442,Google Rewarded US,0,0
END
  #=> 263

File.write(F3, <<~END)
Date,ID,Name,Count,Price
2019-08-27,110146,Amazon In-App,30,70
2019-08-27,121615,Google US Rally,12,50
2019-08-27,208442,Google Rewarded US,15,45
2019-08-28,110146,Amazon In-App,15,55
2019-08-28,121615,Google US Rally,20,60
2019-08-28,208442,Google Rewarded US,0,0
END
  #=> 265

Fout = 'fout.csv'

doit(F1, F2, F3, Fout)

puts File.read(Fout)
Date,ID,Name,Count,Price
2019-08-25,110146,Amazon In-App,1,23
2019-08-25,121615,Google US Rally,0,0
2019-08-25,208442,Google Rewarded US,47,12
2019-08-26,110146,Amazon In-App,30,90
2019-08-26,121615,Google US Rally,5,25
2019-08-26,208442,Google Rewarded US,15,45
2019-08-27,110146,Amazon In-App,30,70
2019-08-27,121615,Google US Rally,12,50
2019-08-27,208442,Google Rewarded US,15,45
2019-08-28,110146,Amazon In-App,15,55
2019-08-28,121615,Google US Rally,20,60
2019-08-28,208442,Google Rewarded US,0,0

请参阅CSV::openCSV::readFile::newIO#getsHash#valuesThis article 可能会对处理 CSV 文件感兴趣。

【讨论】:

  • 我正在使用上述方法处理更多文件。某些文件的列顺序已更改。如果列顺序也发生了变化,我该如何让它工作?
  • 我找到了。这是我需要的“end.values.each { |row| csv_out
猜你喜欢
  • 1970-01-01
  • 2021-12-17
  • 2014-05-17
  • 2019-10-11
  • 2018-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多