2013-08-09 3 views
3

У меня есть около 50 файлов CSV с 60 000 строк в каждом и различное количество столбцов. Я хочу объединить все CSV-файлы по столбцу. Я попытался сделать это в MATLAB, перенести каждый файл csv и повторно сохранить на диск, а затем используя командную строку для их конкатенации. Это заняло мой компьютер в течение недели, и окончательный результат нужно перенести еще раз! Я должен сделать это снова, и я ищу решение, которое не займет еще неделю. Любая помощь будет оценена по достоинству.Какой самый быстрый способ объединить несколько файлов CSV по столбцу?

+0

Вы знакомы с Perl, хотя бы немного? – mvp

+0

Нет, совсем нет. Я знаю C и C++. – ankit

+0

50 раз 60000 строк не звучит как много. Каков общий размер данных? Не подходит ли она в памяти? – paddy

ответ

7

[...] перенося каждый файл CSV и повторно сохранение на диск, а затем с помощью командной строки, чтобы объединить их [...]

Похоже транспозиции-Cat-Транспонирование. Используйте paste для соединения файлов по горизонтали.

paste -d ',' a.csv b.csv c.csv ... > result.csv 
+0

Отличное решение - он может даже объединить очень большие файлы csv, которые даже не загружаются в память (например, в python). Операция выполняется по строкам, поэтому проблем с памятью не возникает. – Tickon

1

Модуль Python csv может быть настроен так, что каждая запись является словарем с именами столбцов в виде ключей. Вы должны таким образом иметь возможность читать во всех файлах как словари и записывать их в файл, содержащий все столбцы.

Python прост в использовании, поэтому это должно быть довольно тривиально для программиста любого языка.

Если у ваших csv-файлов нет заголовков столбцов, это будет довольно много ручной работы, хотя, возможно, это не лучшее решение.

Поскольку эти файлы довольно большие, лучше не читать их все в памяти один раз. Я бы рекомендовал сначала открыть их только для того, чтобы собрать все имена столбцов в список и использовать этот список для создания выходного файла. Затем вы можете объединить каждый входной файл в выходной файл без необходимости иметь все файлы в памяти.

+0

Мои файлы имеют заголовки. Я просто хочу, чтобы все файлы были объединены по горизонтали. Является ли это быстродействием для размеров файлов? (отметьте комментарий к вопросу). – ankit

+0

@ankit: Да, никаких проблем. Обновлен ответ. (Это забавная проблема, если бы у меня было время, я бы сделал это за вас, но я этого не делаю, я должен угодить клиентам. :-)) –

+0

Эй, Леннарт, прежде чем вы отправитесь, не могли бы вы просто перечислить имена функций/методов, которые мне понадобятся? Я могу использовать их для использования и выяснить остальные. Спасибо :) – ankit

1

Горизонтальная конкатенация действительно тривиальна. Учитывая, что вы знаете C++, я удивлен, что вы использовали MATLAB. Обработка GB или так данных в том, как вы делаете, должна быть в секундах, а не в днях.

По вашему описанию, обработка CSV на самом деле не требуется. Самый простой подход - просто сделать это в ОЗУ.

vector< vector<string> > data(num_files); 

for(int i = 0; i < num_files; i++) { 
    ifstream input(filename[i]); 
    string line; 
    while(getline(input, line)) data[i].push_back(line); 
} 

(ли очевидные проверки вменяемости, например, убедившись, что все векторы имеют одинаковую длину ...)

Теперь у вас есть все, дамп:

ofstream output("concatenated.csv"); 

for(int row = 0; row < num_rows; row++) { 
    for(int f = 1; f < num_files; f++) { 
     if(f == 0) output << ","; 
     output << data[f][row]; 
    } 
    output << "\n"; 
} 

Если вы не» t хотите использовать всю эту ОЗУ, вы можете сделать это по одной строке за раз. Вы должны иметь возможность держать все файлы открытыми сразу и просто хранить объекты ifstream в списке vector/array /. В этом случае вы просто читаете по одной строке за раз из каждого файла и записываете его на выход.

+0

Как я понимаю, есть некоторые манипуляции с CSV, что означает, что вам нужно также проанализировать CSV. Так что этого недостаточно. –

1
import csv 
import itertools 

# put files in the order you want concatentated 
csv_names = [...whatever...] 

readers = [csv.reader(open(fn, 'rb')) for fn in csv_names] 
writer = csv.writer(open('result.csv', 'wb')) 

for row_chunks in itertools.izip(*readers): 
    writer.writerow(list(itertools.chain.from_iterable(row_chunks))) 

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

Относится к Python 2.В Python 3, открытие файлов CSV немного отличается:

readers = [csv.reader(open(fn, 'r'), newline='') for fn in csv_names] 
writer = csv.writer(open('result.csv', 'w'), newline='') 
0

Использование Go: https://github.com/chrislusf/gleam

Предположим, есть файл "a.csv" имеет поля "a1, a2, a3, a4, a5".

И предположим, что файл «b.csv» имеет поля «b1, b2, b3».

Мы хотим присоединиться к строкам, где a1 = b2. Формат вывода должен быть «a1, a4, b3».

package main 

import (
    "os" 

    "github.com/chrislusf/gleam" 
    "github.com/chrislusf/gleam/source/csv" 
) 

func main() { 

    f := gleam.New() 
    a := f.Input(csv.New("a.csv")).Select(1,4) // a1, a4 
    b := f.Input(csv.New("b.csv")).Select(2,3) // b2, b3 

    a.Join(b).Fprintf(os.Stdout, "%s,%s,%s\n").Run() // a1, a4, b3 

} 
Смежные вопросы