Применение одинаковых операций к нескольким файлам .csv в пандах - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть шесть файлов .csv. Их общий размер примерно 4 гига. Мне нужно очистить каждого и выполнить некоторые задачи анализа данных на каждом. Эти операции одинаковы для всех кадров. Это мой код для их чтения.

#df = pd.read_csv(r"yellow_tripdata_2018-01.csv")
#df = pd.read_csv(r"yellow_tripdata_2018-02.csv")
#df = pd.read_csv(r"yellow_tripdata_2018-03.csv")
#df = pd.read_csv(r"yellow_tripdata_2018-04.csv")
#df = pd.read_csv(r"yellow_tripdata_2018-05.csv")
df = pd.read_csv(r"yellow_tripdata_2018-06.csv")

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

Ответы [ 4 ]

0 голосов
/ 01 ноября 2018

Используйте glob.glob, чтобы получить все файлы с похожими именами:

import glob
files = glob.glob("yellow_tripdata_2018-0?.csv")
for f in files:
    df = pd.read_csv(f)
    # manipulate df
    df.to_csv(f)

Это будет соответствовать yellow_tripdata_2018-0<any one character>.csv. Вы также можете использовать yellow_tripdata_2018-0*.csv слишком соответствовать yellow_tripdata_2018-0<anything>.csv или даже yellow_tripdata_*.csv, чтобы соответствовать всем CSV-файлам, которые начинаются с yellow_tripdata.

Обратите внимание, что одновременно загружается только один файл.

0 голосов
/ 01 ноября 2018

Используйте os.listdir (), чтобы составить список файлов, которые вы можете циклически просматривать?

samplefiles = os.listdir(filepath)
for filename in samplefiles:
    df = pd.read_csv(filename)

где filepath - это каталог, содержащий несколько CSV-файлов?

Или цикл, который меняет имя файла:

for i in range(1, 7):
    df = pd.read_csv(r"yellow_tripdata_2018-0%s.csv") % ( str(i))
0 голосов
/ 01 ноября 2018

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

number_of_files = 6
dfs = []

for file_num in range(len(number_of_files)):
    dfs.append(pd.read_csv(f"yellow_tripdata_2018-0{file_num}.csv")) #I use Python 3.6, so I'm used to f-strings now. If you're using Python <3.6 use .format()

Затем, чтобы получить определенный фрейм данных, используйте:

df1 = dfs[0]

Edit:

Поскольку вы пытаетесь не загружать все это в память, я бы прибегнул к их потоковой передаче. Попробуйте изменить цикл for на что-то вроде этого:

for file_num in range(len(number_of_files)):
    with open(f"yellow_tripdata_2018-0{file_num}.csv", 'wb') as f:
        dfs.append(csv.reader(iter(f.readline, '')))

Затем просто используйте цикл for dfs[n] или next(dfs[n]), чтобы прочитать каждую строку в память.

приписка

Вам может понадобиться многопоточность для перебора каждого из них в то же время .

Загрузка / редактирование / сохранение: - с использованием csv модуля

Хорошо, так что я провел много исследований, модуль csv python загружает по одной строке за раз, скорее всего, в том режиме, в котором мы его открываем. (объяснено здесь )

Если вы не хотите использовать Pandas (который, честно говоря, может быть ответом, просто включите это в ответ @ seralouk, если так) , иначе, тогда да! Это ниже , на мой взгляд, будет лучшим подходом, нам просто нужно изменить пару вещей.

number_of_files = 6
filename = "yellow_tripdata_2018-{}.csv"

for file_num in range(number_of_files):
    #notice I'm opening the original file as f in mode 'r' for read only
    #and the new file as nf in mode 'a' for append
    with open(filename.format(str(file_num).zfill(2)), 'r') as f,
         open(filename.format((str(file_num)+"-new").zfill(2)), 'a') as nf:
        #initialize the writer before looping every line
        w = csv.writer(nf)
        for row in csv.reader(f):
            #do your "data cleaning" (THIS IS PER-LINE REMEMBER)
        #save to file
        w.writerow(row)

Примечание:

Возможно, вы захотите использовать DictReader и / или DictWriter , я бы предпочел их обычным читателям / писателям, так как мне легче их понять.

Подход Панд - с использованием кусков

ПОЖАЛУЙСТА, ПРОЧИТАЙТЕ этот ответ - если вы хотите отойти от моего подхода CSV и придерживаться Pandas :) В буквальном смысле кажется, что это та же проблема, что и у вас, и ответ - это то, что вы спрашиваю.

В основном Panda позволяет частично загружать файл в виде чанков, выполнять любые изменения, а затем записывать эти чанки в новый файл. Ниже в основном из этого ответа, но я сделал еще немного, читая себя в документах

number_of_files = 6
chunksize = 500 #find the chunksize that works best for you
filename = "yellow_tripdata_2018-{}.csv"

for file_num in range(number_of_files):
    for chunk in pd.read_csv(filename.format(str(file_num).zfill(2))chunksize=ch)
        # Do your data cleaning
        chunk.to_csv(filename.format((str(file_num)+"-new").zfill(2)), mode='a') #see again we're doing it in append mode so it creates the file in chunks

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

0 голосов
/ 01 ноября 2018

Используйте for и format, как это. Я использую это каждый день:

number_of_files = 6

for i in range(1, number_of_files+1):
    df = pd.read_csv("yellow_tripdata_2018-0{}.csv".format(i)))

    #your code here, do analysis and then the loop will return and read the next dataframe
...