CSV - извлечение данных и запись в другой CSV в рубине - PullRequest
0 голосов
/ 25 октября 2018

У меня есть большой файл с именем 'texas_boundaries.csv', который состоит из пар lat / lng, которые описывают сотни границ посещаемости школы.Это файл размером более 800 МБ, который слишком велик для загрузки в heroku.Мне нужны границы только для определенных школ, поэтому я пытаюсь найти только нужные мне строки и записать их в новый файл с таким кодом:

desc "Reduce texas csv to only needed schools"
task :reduce_texas => :environment do

  require 'csv'

  file = "texas_boundaries.csv"
  headers = CSV.open(file, &:readline)
  nces_ids = School.pluck(:nces_id).uniq
  nces_ids_track = nces_ids
  file_name = 'texas_reduced_boundaries.csv'

  CSV.open(file_name, 'a') do |csv|
    csv << headers
  end

  CSV.foreach(file, :headers => true, encoding: "UTF-8") do |row|
    if nces_ids.include?(row['ncessch'])
      CSV.open(file_name, 'a') do |csv|
        csv << row
        p row['ncessch']
        nces_ids_track.delete(row['ncessch'])
      end
    end
  end

  p "Nces_ids not in reduced boundaries file: #{nces_ids_track.count}"
  p nces_ids_track

end

В каждой школе есть десятки точек, которые описывают ее границы,но когда я запускаю этот код, в новом файле записывается только одна точка.Это демонстрируется выводом консоли, где я ожидаю, что один и тот же nces_id будет появляться много раз, прежде чем перейти на новый nces_id.

tomb$ rake reduce_texas
"480000801507"
"480000801508"
"480000806094"
"480000806989"
"480000811280"
"480000905246"

Вот снимок экрана фактического файла данных, который показывает, что есть много строк сnces_id = 480000801507.

texas_boundaries.csv

В новом файле записывается только самая первая строка.

texas_reduced_boundaries.csv

Любая помощь будет принята с благодарностью!Как примечание: этот процесс очень медленный, поэтому, если кто-то из читателей увидит способ ускорить процесс, сообщите мне.

1 Ответ

0 голосов
/ 25 октября 2018

Это выглядит подозрительно:

nces_ids = School.pluck(:nces_id).uniq
nces_ids_track = nces_ids

Назначение не копирует массив nces_ids, оно просто копирует ссылку.В результате nces_ids и nces_ids_track ссылаются на один и тот же массив.Позже вы сделаете это:

if nces_ids.include?(row['ncessch'])
  CSV.open(file_name, 'a') do |csv|
    #...
    nces_ids_track.delete(row['ncessch'])
  end
end

но nces_ids и nces_ids_track ссылаются на один и тот же массив, а не на разные массивы, как ожидалось.

Возможно, вы захотите сказать:

nces_ids = School.pluck(:nces_id).uniq
nces_ids_track = nces_ids.dup
# -----------------------^^^^

чтобы у вас было две копии массива для работы.

...