Разделить файл CSV на основе значений столбцов и количества строк

Я должен работать с данными из огромного файла CSV в таком формате, как вот этот. Файл очень огромен (~ 200 МБ), и мой компьютер испытывает трудности с ним, поэтому я хотел бы разбить файл на более мелкие, с которыми было бы легче справиться. Предположим, что файл имеет такой формат:

NAME,SURNAME,SEX,CITY,AGE RANK
Tom,Brown,M,New York,20-40
Dick,Clarke,M,Seattle,0-20
Katie,Johnson,F,Boston,40-60
Harry,Smith,M,Washington,40-60
Amy,Davies,F,Chicago,20-40
Emily,Adams,F,New York,20-40
...

Я хотел бы разделить его следующим образом:

  • отдельные возрастные категории
  • каждый файл не длиннее заданного номера строки, в противном случае снова разделяется

Например:

  • 0-20.1.csv (5000 строк)
  • 0-20.2.csv (5000 строк)
  • 0-20.3.csv (1234 оставшиеся строки)
  • 20-30.1.csv (5000 строк)
  • 20-30.2.csv (4321 оставшаяся строка)
  • ...

Я также хотел бы повторить первую строку (заголовок) входного файла в начале каждого выходного файла, а также удалить некоторые столбцы, которые я не использую в этом нет необходимости, но это не обязательно. Итак, мой идеальный результат для возрастного ранга 20-40 был бы (предположим, я хочу удалить столбцы ИМЯ и ВОЗРАСТНЫЙ РАНГ ):

SURNAME,SEX,CITY
Brown,M,New York
Davies,F,Chicago
Adams,F,New York
...

Есть ли способ автоматически управлять файлом, например который? Я могу использовать любой инструмент или сценарий, но я бы предпочел избегать проприетарного программного обеспечения.

1
задан 11 July 2020 в 11:36

1 ответ

It would be helpful if you included a mini-example with enough data for splitting at, say, 5 lines instead of 5000. However, you should be able to use something like this, in Awk:

awk -F, -v nsplit=5000 '
  NR==1 {OFS=FS; hdr=$0; next} 
  (++count[$5] % nsplit == 1) {
    close(fname[$5]); 
    fname[$5] = $5 "." (++ind[$5]) ".csv";
    print hdr > fname[$5]
  } 
  {print > fname[$5]}
' file.csv

Testing with nsplit=2:

$ awk -F, -v nsplit=2 '
  NR==1 {OFS=FS; hdr=$0; next} 
  (++count[$5] % nsplit == 1) {
    close(fname[$5]); 
    fname[$5] = $5 "." (++ind[$5]) ".csv";
    print hdr > fname[$5]
  } 
  {print > fname[$5]}
' file.csv

gives

$ head 0-20.?.csv 20-40.?.csv 40-60.?.csv 
==> 0-20.1.csv <==
NAME,SURNAME,SEX,CITY,AGE RANK
Dick,Clarke,M,Seattle,0-20

==> 20-40.1.csv <==
NAME,SURNAME,SEX,CITY,AGE RANK
Tom,Brown,M,New York,20-40
Amy,Davies,F,Chicago,20-40

==> 20-40.2.csv <==
NAME,SURNAME,SEX,CITY,AGE RANK
Emily,Adams,F,New York,20-40

==> 40-60.1.csv <==
NAME,SURNAME,SEX,CITY,AGE RANK
Katie,Johnson,F,Boston,40-60
Harry,Smith,M,Washington,40-60
1
ответ дан 30 July 2020 в 22:10

Другие вопросы по тегам:

Похожие вопросы: