Импортируйте несколько файлов csv в pandas и объедините в один DataFrame
Я хотел бы прочитать несколько файлов csv из каталога в pandas и объединить их в один большой DataFrame. Однако я не смог понять это. Вот что я до сих пор:
import glob
import pandas as pd
# get data file names
path =r'C:\DRO\DCL_rawdata_files'
filenames = glob.glob(path + "/*.csv")
dfs = []
for filename in filenames:
dfs.append(pd.read_csv(filename))
# Concatenate all data into one DataFrame
big_frame = pd.concat(dfs, ignore_index=True)
Я думаю, мне нужна помощь в цикле for.
Ответы
Ответ 1
Если у вас одинаковые столбцы во всех ваших csv
файлах, вы можете попробовать код ниже. Я добавил header=0
чтобы после прочтения csv
первой строке можно было присвоить имена столбцов.
import pandas as pd
import glob
path = r'C:\DRO\DCL_rawdata_files' # use your path
all_files = glob.glob(path + "/*.csv")
li = []
for filename in all_files:
df = pd.read_csv(filename, index_col=None, header=0)
li.append(df)
frame = pd.concat(li, axis=0, ignore_index=True)
Ответ 2
Альтернатива ответ darindaCoder:
path = r'C:\DRO\DCL_rawdata_files' # use your path
all_files = glob.glob(os.path.join(path, "*.csv")) # advisable to use os.path.join as this makes concatenation OS independent
df_from_each_file = (pd.read_csv(f) for f in all_files)
concatenated_df = pd.concat(df_from_each_file, ignore_index=True)
# doesn't create a list, nor does it append to one
Ответ 3
import glob, os
df = pd.concat(map(pd.read_csv, glob.glob(os.path.join('', "my_files*.csv"))))
Ответ 4
Библиотека Dask может читать данные из нескольких файлов:
>>> import dask.dataframe as dd
>>> df = dd.read_csv('data*.csv')
(Источник: http://dask.pydata.org/en/latest/examples/dataframe-csv.html).
Фреймы данных Dask реализуют подмножество API фреймов данных Pandas. Если все данные df.compute()
в память, вы можете вызвать df.compute()
чтобы преобразовать df.compute()
данных в df.compute()
Pandas.
Ответ 5
Почти все ответы здесь либо излишне сложны (сопоставление с шаблоном), либо полагаются на дополнительные сторонние библиотеки. Вы можете сделать это в 2 строки, используя все, что уже встроено в Pandas и python (все версии).
Для нескольких файлов - 1 вкладыш:
df = pd.concat(map(pd.read_csv, ['data/d1.csv', 'data/d2.csv','data/d3.csv']))
Для многих файлов:
from os import listdir
filepaths = [f for f in listdir("./data") if f.endswith('.csv')]
df = pd.concat(map(pd.read_csv, filepaths))
Эта строка панд, которая устанавливает df, использует 3 вещи:
- Карта Python (функция, итерируемая) отправляет в функцию (
pd.read_csv()
) итерацию (наш список), которая является каждым элементом csv в пути к файлам). - Функция Panda read_csv() читает в каждом файле CSV как обычно.
- Panda concat() объединяет все это в одну переменную df.
Ответ 6
Изменить: я googled мой путь в fooobar.com/questions/45779/....
Однако в последнее время я нахожу более быстрым делать какие-либо манипуляции с помощью numpy, а затем назначать его один раз на dataframe, а не манипулировать самим фреймворком на итеративной основе и, похоже, тоже работает в этом решении.
Я искренне хочу, чтобы кто-то нажал эту страницу, чтобы рассмотреть этот подход, но не хочу прикладывать эту огромную часть кода в качестве комментария и сделать ее менее читаемой.
Вы можете использовать numpy, чтобы действительно ускорить конкатенацию dataframe.
import os
import glob
import pandas as pd
import numpy as np
path = "my_dir_full_path"
allFiles = glob.glob(os.path.join(path,"*.csv"))
np_array_list = []
for file_ in allFiles:
df = pd.read_csv(file_,index_col=None, header=0)
np_array_list.append(df.as_matrix())
comb_np_array = np.vstack(np_array_list)
big_frame = pd.DataFrame(comb_np_array)
big_frame.columns = ["col1","col2"....]
Сроки:
total files :192
avg lines per file :8492
--approach 1 without numpy -- 8.248656988143921 seconds ---
total records old :1630571
--approach 2 with numpy -- 2.289292573928833 seconds ---
Ответ 7
Если вы хотите выполнить рекурсивный поиск (Python 3.5 или выше), вы можете сделать следующее:
from glob import iglob
import pandas as pd
path = r'C:\user\your\path\**\*.csv'
all_rec = iglob(path, recursive=True)
dataframes = (pd.read_csv(f) for f in all_rec)
big_dataframe = pd.concat(dataframes, ignore_index=True)
Обратите внимание, что три последние строки могут быть выражены в одной строке:
df = pd.concat((pd.read_csv(f) for f in iglob(path, recursive=True)), ignore_index=True)
Вы можете найти документацию **
здесь. Также я использовал iglob
вместо glob
, так как он возвращает итератор вместо списка.
РЕДАКТИРОВАТЬ: Мультиплатформенная рекурсивная функция:
Вы можете обернуть вышеупомянутое в многоплатформенную функцию (Linux, Windows, Mac), так что вы можете сделать:
df = read_df_rec('C:\user\your\path', *.csv)
Вот функция:
from glob import iglob
from os.path import join
import pandas as pd
def read_df_rec(path, fn_regex=r'*.csv'):
return pd.concat((pd.read_csv(f) for f in iglob(
join(path, '**', fn_regex), recursive=True)), ignore_index=True)
Ответ 8
Если несколько CSV файлов заархивированы, вы можете использовать zipfile, чтобы прочитать все и объединить, как показано ниже:
import zipfile
import numpy as np
import pandas as pd
ziptrain = zipfile.ZipFile('yourpath/yourfile.zip')
train=[]
for f in range(0,len(ziptrain.namelist())):
if (f == 0):
train = pd.read_csv(ziptrain.open(ziptrain.namelist()[f]))
else:
my_df = pd.read_csv(ziptrain.open(ziptrain.namelist()[f]))
train = (pd.DataFrame(np.concatenate((train,my_df),axis=0),
columns=list(my_df.columns.values)))
Ответ 9
Легко и быстро
Импортируйте два или более csv
без необходимости составлять список имен.
import glob
df = pd.concat(map(pd.read_csv, glob.glob('data/*.csv')))
Ответ 10
Я нашел этот метод довольно элегантным.
import pandas as pd
import os
big_frame = pd.DataFrame()
for file in os.listdir():
if file.endswith('.csv'):
df = pd.read_csv(file)
big_frame = big_frame.append(df, ignore_index=True)
Ответ 11
один лайнер, использующий map
, но если вы хотите указать дополнительные аргументы, вы можете сделать:
import pandas as pd
import glob
import functools
df = pd.concat(map(functools.partial(pd.read_csv, sep='|', compressed=None),
glob.glob("data/*.csv")))
Примечание: map
сама по себе не позволяет вводить дополнительные аргументы.
Ответ 12
Еще один on-liner со списком, который позволяет использовать аргументы с read_csv.
df = pd.concat([pd.read_csv(f'dir/{f}') for f in os.listdir('dir') if f.endswith('.csv')])
Ответ 13
На основании @Sid хороший ответ.
Перед объединением вы можете загрузить CSV файлы в промежуточный словарь, который предоставляет доступ к каждому набору данных на основе имени файла (в форме dict_of_df['filename.csv']
). Такой словарь может помочь вам выявить проблемы с разнородными форматами данных, например, когда имена столбцов не выровнены.
Импортируйте модули и найдите пути к файлам:
import os
import glob
import pandas
from collections import OrderedDict
path =r'C:\DRO\DCL_rawdata_files'
filenames = glob.glob(path + "/*.csv")
Примечание: OrderedDict
не обязательно,
но он сохранит порядок файлов, которые могут быть полезны для анализа.
Загрузите CSV файлы в словарь. Затем объедините:
dict_of_df = OrderedDict((f, pandas.read_csv(f)) for f in filenames)
pandas.concat(dict_of_df, sort=True)
Ключи - это имена файлов f
, а значения - содержимое фрейма данных CSV файлов.
Вместо использования f
в качестве ключа словаря, вы также можете использовать os.path.basename(f)
или другие методы os.path, чтобы уменьшить размер ключа в словаре до только меньшей части, которая имеет отношение к делу.
Ответ 14
Альтернатива с использованием библиотеки pathlib
(часто предпочтительнее, чем os.path
).
Этот метод позволяет избежать многократного использования панд concat()
/apped()
.
Из документации панд:
Стоит отметить, что concat() (и, следовательно, append()) создает полную копию данных, и что постоянное повторное использование этой функции может привести к значительному снижению производительности. Если вам нужно использовать операцию над несколькими наборами данных, используйте понимание списка.
import pandas as pd
from pathlib import Path
dir = Path("../relevant_directory")
df = (pd.read_csv(f) for f in dir.glob("*.csv"))
df = pd.concat(df)