Birden fazla csv dosyasını pandalara aktarın ve bir DataFrame'e birleştirin


403

Bir dizinden pandalara birkaç csv dosyası okumak ve bunları büyük bir DataFrame'e birleştirmek istiyorum. Yine de anlayamadım. Şimdiye kadar sahip olduğum şey:

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)

Sanırım for döngüsü içinde biraz yardıma ihtiyacım var ???


Eğer eklemeden olmadığı için kodunuzu şey yapmaz dfslistede, sınırı değiştirmek istemiyorum data = pd.read_csv(filename)ile dfs.append(pd.read_csv(filename). O zaman liste üzerinde döngü gerekir ve concatben concatbir dfs listesi üzerinde çalışacağını sanmıyorum .
EdChum

Ayrıca size son satırında modül adıyla modül için bir takma ad karıştırma, bu olmamalı big_frame = pd.concat(dfs, ignore_index=True)? Eğer listede ve concat üzerinde yineleme gerekecektir dataframes bir listesi var zaten bir kere,big_frame
EdChum

Evet, kodu düzenledim, ama yine de csv dosyalarından birleştirilmiş bir veri çerçevesi oluşturamıyorum, bu konuda biraz daha yardıma ihtiyacım var
jonas 15

dfsŞimdi döngü for df in dfs: big_frame.concat(df, ignore_index=True)yapmalısınız , böylece böyle bir şey çalışmalı, appendbunun yerine deneyebilirsiniz concat.
EdChum

Neyin işe yaramadığını daha iyi söyleyebilir misiniz? Çünkü concatDataFrame'lerin bir listesini yaptığınız gibi iyi işlemelisiniz. Bence bu çok iyi bir yaklaşım.
joris

Yanıtlar:


455

Tüm csvdosyalarınızda aynı sütunlar varsa, aşağıdaki kodu deneyebilirsiniz. Ben ilk satır header=0okuduktan sonra csvsütun adları olarak atanabilir böylece ekledim .

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)

Bu eski moda bir şey yapmak gibi görünüyor, esp. Hapood ekosistemi, farklı dosya türlerini (csv, json, txt, veritabanları) içeren birçok farklı dizinde doğrudan bir veri kaynağıymış gibi sql sorguları gerçekleştirebileceğiniz büyüyen araç listesine sahiptir. Python'da benzer bir şey olmalı, çünkü "büyük veri" yapmaya 20 yıllık bir sıçrama başlattı.
Hexatonic

275
Aynı şey daha kısa ve belki de bir liste kullanmadığı için daha hızlı: df = pd.concat((pd.read_csv(f) for f in all_files)) Ayrıca, belki de os.path.join(path, "*.csv")yerine kullanmalı path + "/*.csv", bu da işletim sistemini bağımsız hale getirir.
Sid

4
Bu yanıtı kullanarak dosya adı ile yeni bir sütun eklememe izin verdi örneğin df['filename'] = os.path.basename(file_)for file_ loop ile .. Sid'in cevabının buna izin verip vermediğinden emin değil misiniz?
curtisp

4
@curtisp hala Sid'in cevabı ile yapabilirsiniz, sadece pandas.read_csv(f).assign(filename = foo)jeneratörün içinde kullanın . assignyeni sütun da dahil olmak üzere tüm veri çerçevesini döndürürfilename
C8H10N4O2

Eğer varsa birçok dosya, bir jeneratör kullanmak yerine hepsini birleştirerek önce bir liste için + dosya eklemeyi ithal ederim.
gustafbstrom

289

DarindaCoder'ün cevabına bir alternatif :

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

2
@Sid @ Mike son iki hat ile ikame edilmiş olabilir: pd.concat((pd.read_csv(f) for f in all_files), ignore_index=True). İç braketler Pandalar 0.18.1 sürümü için gereklidir
Igor Fobia

6
Bunun glob.iglobyerine kullanmanızı öneririm glob.glob; Birincisi döner ve yineleyici (liste yerine) .
toto_tico

54
import glob, os    
df = pd.concat(map(pd.read_csv, glob.glob(os.path.join('', "my_files*.csv"))))

4
Mükemmel bir astar, read_csv argümanı gerekmiyorsa özellikle kullanışlıdır!
rafaelvalle

15
Öte yandan, argümanlara ihtiyaç duyulursa, bu lambdas ile yapılabilir:df = pd.concat(map(lambda file: pd.read_csv(file, delim_whitespace=True), data_files))
fiedl

^ veya ile functools.partial, lambdas önlemek için
cs95


30

Buradaki cevapların neredeyse tamamı gereksiz yere karmaşıktır (glob patern eşleşmesi) veya ek 3. taraf kitaplıklarına dayanır. Pandalar ve python (tüm sürümler) zaten yerleşik olan her şeyi kullanarak 2 satırda yapabilirsiniz.

Birkaç dosya için - 1 astar:

df = pd.concat(map(pd.read_csv, ['data/d1.csv', 'data/d2.csv','data/d3.csv']))

Birçok dosya için:

from os import listdir

filepaths = [f for f in listdir("./data") if f.endswith('.csv')]
df = pd.concat(map(pd.read_csv, filepaths))

Df'yi ayarlayan bu panda hattı 3 şey kullanır:

  1. Python'un haritası (işlev, yinelenebilir), dosyapd.read_csv() yollarındaki her csv öğesi olan yinelenebilir (listemiz) işlevine gönderir .
  2. Panda'nın read_csv () işlevi her bir CSV dosyasında normal olarak okunur.
  3. Panda'nın concat () tüm bunları bir df değişkeninin altına getirir.

3
ya da sadecedf = pd.concat(map(pd.read_csv, glob.glob('data/*.csv))
müon

@Muon tarafından önerilen yöntemi denedim. Ancak, üstbilgi ile birden fazla dosya var (başlıklar ortak). Veri çerçevesinde birleştirilmelerini istemiyorum. Bunu nasıl yapabilirim biliyor musun? Denedim df = pd.concat(map(pd.read_csv(header=0), glob.glob('data/*.csv))ama bir hata verdi "parser_f () eksik 1 gerekli konumsal argüman: 'filepath_or_buffer'"
cadip92

14

Düzenleme: https://stackoverflow.com/a/21232849/186078 içine yolumu googled . Ancak geç kalmış olsa da numpy kullanarak herhangi bir manipülasyon yapmak ve daha sonra veri çerçevesinin kendisini yinelemeli olarak manipüle etmek yerine bir kez veri çerçevesine atamak daha hızlı buluyorum ve bu çözüm de çalışıyor gibi görünüyor.

İçtenlikle bu sayfaya isabet eden herkesin bu yaklaşımı dikkate almasını istiyorum, ancak bu büyük kod parçasını yorum olarak eklemek ve daha az okunabilir hale getirmek istemiyorum.

Veri çerçevesi birleştirmesini gerçekten hızlandırmak için numpy'den yararlanabilirsiniz.

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"....]

Zamanlama istatistikleri:

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 ---

Herhangi bir sayı "hızlandırmak" için? Özellikle, stackoverflow.com/questions/20906474/… ' den daha hızlı mı?
ivan_pozdeev

OP'nin birleşimini hızlandırmanın bir yolunu istediğini görmüyorum, bu sadece önceden var olan kabul edilmiş bir cevabın yeniden çalışması gibi görünüyor.
pydsigner

2
Verilerin karışık sütun türleri varsa bu işe yaramaz.
Pimin Konstantin Kefaloukos

1
@SKG mükemmel .. bu benim için tek çalışan çözüm. 500 dosya, 2 saniyede toplam 400 bin satır. Gönderdiğiniz için teşekkürler.
FrankC

11

Yinelemeli olarak arama yapmak istiyorsanız ( Python 3.5 veya üstü ), aşağıdakileri yapabilirsiniz:

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)

Son üç satırın tek bir satırda ifade edilebileceğini unutmayın :

df = pd.concat((pd.read_csv(f) for f in iglob(path, recursive=True)), ignore_index=True)

Belgelerini ** burada bulabilirsiniz . Ayrıca, kullanılan iglobyerine globbir döner gibi yineleyici listesi yerine.



EDIT: Çok platformlu özyinelemeli işlev:

Yukarıdakileri çok platformlu bir işleve (Linux, Windows, Mac) sarabilirsiniz , böylece şunları yapabilirsiniz:

df = read_df_rec('C:\user\your\path', *.csv)

İşte işlevi:

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)

11

Kolay ve Hızlı

csvBir ad listesi yapmak zorunda kalmadan iki veya daha fazlasını içe aktarın .

import glob

df = pd.concat(map(pd.read_csv, glob.glob('data/*.csv')))

8

bir astar kullanıyor map, ancak ek bağımsız değişkenler belirtmek isterseniz şunları yapabilirsiniz:

import pandas as pd
import glob
import functools

df = pd.concat(map(functools.partial(pd.read_csv, sep='|', compression=None), 
                    glob.glob("data/*.csv")))

Not: maptek başına ek argümanlar sağlamanıza izin vermez.


4

Birden çok csv dosyası sıkıştırılmışsa, tümünü okumak ve aşağıdaki gibi birleştirmek için zipfile kullanabilirsiniz:

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)))

4

Read_csv ile argümanların kullanılmasına izin veren liste kavrama özelliğine sahip bir başka astar.

df = pd.concat([pd.read_csv(f'dir/{f}') for f in os.listdir('dir') if f.endswith('.csv')])

3

@ Sid'in iyi cevabına dayanarak.

Birleştirmeden önce, csv dosyalarını, dosya adına (formda dict_of_df['filename.csv']) dayalı olarak her veri kümesine erişim sağlayan bir ara sözlüğe yükleyebilirsiniz . Böyle bir sözlük, örneğin sütun adları hizalanmadığında heterojen veri formatlarıyla ilgili sorunları belirlemenize yardımcı olabilir.

Modülleri içe aktarın ve dosya yollarını bulun:

import os
import glob
import pandas
from collections import OrderedDict
path =r'C:\DRO\DCL_rawdata_files'
filenames = glob.glob(path + "/*.csv")

Not: OrderedDictgerekli değildir, ancak analiz için yararlı olabilecek dosyaların sırasını koruyacaktır.

Csv dosyalarını sözlüğe yükleyin. Sonra birleştirin:

dict_of_df = OrderedDict((f, pandas.read_csv(f)) for f in filenames)
pandas.concat(dict_of_df, sort=True)

Anahtarlar dosya adlarıdır fve değerler csv dosyalarının veri çerçevesi içeriğidir. fSözlük anahtarı olarak kullanmak yerine, sözlükteki anahtarın boyutunu yalnızca ilgili daha küçük kısma küçültmek için os.path.basename(f)veya diğer os.path yöntemlerini kullanabilirsiniz.


3

pathlibKütüphaneyi kullanmak için alternatif (genellikle tercih ediliros.path ).

Bu yöntem, tekrarlanan panda kullanımını önler concat()/apped() .

Panda belgelerinden:
concat () (ve dolayısıyla append ()) 'in verilerin tam bir kopyasını yaptığını ve bu işlevi sürekli olarak yeniden kullanmanın önemli bir performans isabeti yaratabileceğini belirtmek gerekir. İşlemi birkaç veri kümesi üzerinde kullanmanız gerekiyorsa, bir liste kavrayışı kullanın.

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)

-2

Google Drive'da Colab'ı kullanarak bu şekilde yapabilirsiniz

import pandas as pd
import glob

path = r'/content/drive/My Drive/data/actual/comments_only' # 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,sort=True)
frame.to_csv('/content/drive/onefile.csv')

-3
import pandas as pd
import glob

path = r'C:\DRO\DCL_rawdata_files' # use your path
file_path_list = glob.glob(path + "/*.csv")

file_iter = iter(file_path_list)

list_df_csv = []
list_df_csv.append(pd.read_csv(next(file_iter)))

for file in file_iter:
    lsit_df_csv.append(pd.read_csv(file, header=0))
df = pd.concat(lsit_df_csv, ignore_index=True)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.