Memisahkan CSV 7 juta baris dengan kolom tertentu


2

Bagaimana saya akan membagi file CSV yang sangat besar (7 juta baris) menjadi beberapa lembar / file berbeda dengan kolom numerik tertentu. Itu harus dibagi menjadi sekitar 10 file yang berbeda.


Bagaimana sebenarnya pembagian file? Setiap kolom menuju ke file yang berbeda?
Cristian Ciupitu

Pada sistem operasi apa, program, dll? (misal Windows + Excel, Linux + Libreoffice ...)
Wilf

@CristianCiupitu Saya ingin membagi data berdasarkan 1 kolom. 1 kolom itu memiliki sekitar 10 nilai berbeda. Jadi saya ingin menempatkan setiap baris dengan nilai kolomnya yang dihormati ke dalam file terpisah. Jadi harus keluar ke 10 file berbeda.
BrandonMXB

Jawaban:


3

Gunakan program Python 3 ini:

#!/usr/bin/env python3
import binascii
import csv
import os.path
import sys
from tkinter.filedialog import askopenfilename, askdirectory
from tkinter.simpledialog import askinteger

def split_csv_file(f, dst_dir, keyfunc):
    csv_reader = csv.reader(f)
    csv_writers = {}
    for row in csv_reader:
        k = keyfunc(row)
        if k not in csv_writers:
            csv_writers[k] = csv.writer(open(os.path.join(dst_dir, k),
                                             mode='w', newline=''))
        csv_writers[k].writerow(row)

def get_args_from_cli():
    input_filename = sys.argv[1]
    column = int(sys.argv[2])
    dst_dir = sys.argv[3]
    return (input_filename, column, dst_dir)

def get_args_from_gui():
    input_filename = askopenfilename(
        filetypes=(('CSV', '.csv'),),
        title='Select CSV Input File')
    column = askinteger('Choose Table Column', 'Table column')
    dst_dir = askdirectory(title='Select Destination Directory')
    return (input_filename, column, dst_dir)

if __name__ == '__main__':
    if len(sys.argv) == 1:
        input_filename, column, dst_dir = get_args_from_gui()
    elif len(sys.argv) == 4:
        input_filename, column, dst_dir = get_args_from_cli()
    else:
        raise Exception("Invalid number of arguments")
    with open(input_filename, mode='r', newline='') as f:
        split_csv_file(f, dst_dir, lambda r: r[column-1]+'.csv')
        # if the column has funky values resulting in invalid filenames
        # replace the line from above with:
        # split_csv_file(f, dst_dir, lambda r: binascii.b2a_hex(r[column-1].encode('utf-8')).decode('utf-8')+'.csv')

Simpan sebagai split-csv.pydan jalankan dari Explorer atau dari baris perintah.

Misalnya untuk membagi superuser.csvberdasarkan kolom 1 dan menulis file output yang dstdirdigunakan:

python split-csv.py superuser.csv 1 dstdir

Jika Anda menjalankannya tanpa argumen, GUI berbasis Tkinter akan meminta Anda untuk memilih file input, kolom (1 indeks berbasis) dan direktori tujuan.


Iya! Terima kasih banyak! Sebenarnya berhasil. Saya baru saja akan menggunakan pengkodean naskah untuk menyelesaikan pekerjaan, di Jawa. Tapi woo!
BrandonMXB

Saya senang itu berhasil. Jika saya tahu Anda adalah pengguna yang kuat, saya tidak akan membuang waktu dengan GUI :-)
Voting

Tidaaaak haha. Saya sangat menikmati GUI haha. Saya memang memilih Anda sebagai jawabannya tetapi sayangnya karena saya baru saja bergabung dengan komunitas ini, saya perlu lebih banyak perwakilan. Saya biasanya di komunitas StackOverflow haha. Dan hmm ... Untuk beberapa alasan setelah Anda menulis baris, itu menulis baris lain. Ada saran? Agak menyebalkan bahwa setiap baris lainnya kosong.
BrandonMXB

Saya melihat. Ngomong-ngomong, saya memilih jawaban awk . Saya tidak mengerti soal baris kosong. Mungkin itu ada hubungannya dengan akhir baris. Periksa file dengan editor (mungkin vim ).
Cristian Ciupitu

@BrandonMXB, coba lagi, saya pikir saya sudah memperbaiki masalahnya.
Cristian Ciupitu

5

Ini bisa sesederhana one-liner ini dengan awk:

awk -F ',' '{ print > ("split-" $1 ".csv") }' 7mil.csv
  • File input di sini adalah 7mil.csv
  • Nomor kolom penentu ditunjukkan dengan tanda dolar. Jika itu kolom ketiga, itu $3bukan$1
  • Nilai kolom digunakan untuk menghasilkan nama file yang dihasilkan. Jadi misalnya, setiap baris dengan nilai 42akan berada dalam file bernamasplit-42.csv
  • Pemisah bidang adalah koma
    • yang bekerja karena / jika nilainya numerik, dan tidak memiliki tanda kutip yang perlu dilucuti
    • tetapi juga mensyaratkan bahwa tidak ada koma dalam string apa pun dalam file (setidaknya tidak sebelum kolom angka)

Jadi ini hanya membaca setiap baris dan mencetaknya ke file yang sesuai dengan nilainya. Perhatikan bahwa itu menambah file, jadi jika Anda menjalankannya dua kali, semua data akan digandakan; jadi pastikan tidak ada file dengan pola penamaan itu untuk memulai:del split-*.cvs

Bagian yang sulit untuk mencoba ini adalah menginstal awkpada Windows. Ada gawk untuk Windows dan beberapa tips untuk menjalankannya di sini .


Saya yakin ini akan berhasil juga, tetapi saya melihat solusi di atas terlebih dahulu. Terima kasih banyak! :)
BrandonMXB

1
@ Ken: Jawaban Anda sangat kami hargai! One-liner ini adalah apa yang saya butuhkan untuk pipa data pada sistem Linux :)
Jubbles

1

Delimit dapat melakukannya. Ini membuka file csv besar yang sangat cepat ("hingga 2 miliar baris dan 2 juta kolom besar!"). Gunakan pemisahan secara vertikal dan / atau pilih kolom Anda.

Perangkat lunak lain yang mungkin dapat melakukannya adalah Emeditor .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.