कई सीएसवी फ़ाइलों को पंडों में आयात करें और एक DataFrame में संक्षिप्त करें


403

मैं एक निर्देशिका से कई सीएसवी फ़ाइलों को पंडों में पढ़ना चाहता हूं और उन्हें एक बड़े डेटाफ़्रेम में सम्मिलित करना चाहता हूं। मैं हालांकि यह पता लगाने में सक्षम नहीं है। यह है, जो कि अभी तक मेरे पास है:

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)

मुझे लगता है कि मुझे पाश के लिए कुछ मदद चाहिए ???


क्योंकि आप अपने नहीं जोड़ रहे अपने कोड कुछ नहीं करता है dfsसूची, नहीं है आप लाइन बदलना चाहते हैं data = pd.read_csv(filename)के साथ dfs.append(pd.read_csv(filename)। फिर आपको सूची पर लूप करने की आवश्यकता होगी और concat, मुझे नहीं लगता कि एस की concatसूची पर काम करेगा df
EdChum

यह भी कि आप अपनी अंतिम पंक्ति में मॉड्यूल नाम के साथ मॉड्यूल के लिए एक उपनाम मिला रहे हैं, क्या ऐसा नहीं होना चाहिए big_frame = pd.concat(dfs, ignore_index=True)? वैसे भी एक बार जब आपके पास big_frame
डेटाफ्रेम की

हां, मैंने कोड को संपादित किया है, लेकिन मैं अभी भी सीएसवी-फाइलों से एक संक्षिप्त डेटाफ्रेम का निर्माण करने में सक्षम नहीं हूं, मैं अजगर के लिए नया हूं इसलिए मुझे इस पर कुछ और मदद की आवश्यकता है
जोनास

आपको dfsअब लूप करने की आवश्यकता है , इसलिए कुछ for df in dfs: big_frame.concat(df, ignore_index=True)काम करना चाहिए, आप appendइसके बजाय भी प्रयास कर सकते concatहैं।
EdChum

क्या आप अधिक सटीक रूप से बता सकते हैं कि क्या काम नहीं कर रहा है? क्योंकि concatजैसा आपने किया ठीक वैसे ही DataFrames की सूची को संभालना चाहिए। मुझे लगता है कि यह एक बहुत अच्छा तरीका है।
joris

जवाबों:


454

यदि आपकी सभी 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)

ऐसा लगता है कि पुराने जमाने के उर्फ ​​मैनुअल तरीके से बातें करना, जासूसी करना। जैसा कि हापुड इकोसिस्टम में ऐसे टूल की बढ़ती सूची है जहां आप विभिन्न फ़ाइल प्रकारों (csv, json, txt, डेटाबेस) से सीधे कई अलग-अलग निर्देशिकाओं पर sql क्वेरी कर सकते हैं जैसे कि यह एक डेटा स्रोत था। अजगर में भी कुछ ऐसा ही होना चाहिए, क्योंकि यह "बड़ा डेटा" करने के लिए 20 साल की शुरुआत कर चुका है।
हेक्साटोनिक

275
एक ही चीज़ अधिक संक्षिप्त होती है, और शायद जितनी तेज़ी से यह एक सूची का उपयोग नहीं करता है: df = pd.concat((pd.read_csv(f) for f in all_files)) इसके अलावा, एक को शायद os.path.join(path, "*.csv")इसके बजाय उपयोग करना चाहिए path + "/*.csv", जो इसे ओएस स्वतंत्र बनाता है।
सिड

4
इस उत्तर का उपयोग करने से मुझे फ़ाइल नाम के साथ नया कॉलम जोड़ने की अनुमति मिली जैसे df['filename'] = os.path.basename(file_)कि file_ पाश के लिए .. यदि सिड का उत्तर इसकी अनुमति देता है तो सुनिश्चित नहीं है?
curtisp

4
@ कर्टिसिप आप अभी भी सिड के जवाब के साथ कर सकते हैं, बस pandas.read_csv(f).assign(filename = foo)जनरेटर के अंदर का उपयोग करें । assignनए स्तंभfilename
C8H10N4O2

यदि आपके पास कई फाइलें हैं, तो मैं उन सभी को संक्षिप्त करने से पहले सूची में आयात करने + के बजाय एक जनरेटर का उपयोग करूंगा।
gustafbstrom

289

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

2
@Sid @Mike अंतिम दो पंक्तियों द्वारा प्रतिस्थापित किया जा सकता है: pd.concat((pd.read_csv(f) for f in all_files), ignore_index=True)। भीतरी कोष्ठकों की आवश्यकता पंडों के संस्करण ०.१ brack.१
इगोर फ़ोबिया

6
मैं glob.iglobइसके बजाय का उपयोग करने की सलाह देता हूं glob.glob; पहला एक रिटर्न और इट्रेटर (एक सूची के बजाय)
toto_tico

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

4
उत्कृष्ट एक लाइनर, विशेष रूप से उपयोगी अगर कोई read_csv तर्कों की आवश्यकता नहीं है!
राफेलवावल

15
यदि, दूसरी ओर, तर्कों की आवश्यकता होती है, तो यह df = pd.concat(map(lambda file: pd.read_csv(file, delim_whitespace=True), data_files))
लंबोदर के

^ या साथ functools.partial, लैम्ब्डा से बचने के लिए
cs95

34

Dask लाइब्रेरी एकाधिक फ़ाइलों से डेटाफ्रेम पढ़ सकती है:

>>> import dask.dataframe as dd
>>> df = dd.read_csv('data*.csv')

(स्रोत: http://dask.pydata.org/en/latest/examples/dataframe-csv.html )

Dask डेटाफ़्रेम पंडों डेटाफ़्रेम एपीआई के एक सबसेट को लागू करते हैं। यदि सभी डेटा मेमोरी में फिट बैठता है, तो आप डेटाफ़्रेम को पंडों के डेटाफ़्रेम में बदलने के लिए कॉलdf.compute() कर सकते हैं ।


30

यहां लगभग सभी उत्तर या तो अनावश्यक रूप से जटिल हैं (ग्लोब पैटर्न मिलान) या अतिरिक्त 3 पार्टी पुस्तकालयों पर निर्भर हैं। आप पंडों और अजगर (सभी संस्करणों) में पहले से निर्मित सभी चीजों का उपयोग करके 2 लाइनों में ऐसा कर सकते हैं।

कुछ फ़ाइलों के लिए - 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 चीजों का उपयोग करती है:

  1. पायथन का नक्शा (फ़ंक्शन, iterable) फ़ंक्शन ( pd.read_csv())) iterable (हमारी सूची) को भेजता है जो फ़ाइलपैथ में प्रत्येक csv तत्व है)।
  2. पांडा का read_csv () फ़ंक्शन प्रत्येक CSV फ़ाइल में सामान्य रूप से पढ़ता है।
  3. पांडा का कंसैट () इन सभी को एक डीएफ चर के तहत लाता है।

3
या सिर्फdf = pd.concat(map(pd.read_csv, glob.glob('data/*.csv))
muon

मैंने @muon द्वारा निर्धारित विधि की कोशिश की। लेकिन, मेरे पास हेडर के साथ कई फाइलें हैं (हेडर आम हैं)। मैं उन्हें डेटाफ़्रेम में समाप्‍त नहीं करना चाहता। क्या आप जानते हैं कि मैं ऐसा कैसे कर सकता हूं? मैंने कोशिश की, df = pd.concat(map(pd.read_csv(header=0), glob.glob('data/*.csv))लेकिन इसने एक त्रुटि दी "parser_f () 1 आवश्यक स्थिति संबंधी तर्क गायब है: 'filepath_or_buffer'"
Cadip92

14

संपादित करें: मैंने अपना रास्ता https://stackoverflow.com/a/21232849/186078 में देखा । हालांकि देर से मैं इसे तेजी से सुन्नता का उपयोग करने के लिए किसी भी हेरफेर करने के लिए पा रहा हूं और फिर इसे डेटाफ्रेम के हेरफेर के आधार पर डेटाफ्रेम करने के बजाय इसे एक बार असाइन करना है और यह इस समाधान में भी काम करने लगता है।

मैं ईमानदारी से किसी को भी इस दृष्टिकोण पर विचार करने के लिए इस पृष्ठ को मारना चाहता हूं, लेकिन इस विशाल कोड को टिप्पणी के रूप में संलग्न नहीं करना चाहता और इसे कम पठनीय बना सकता हूं।

आप वास्तव में डेटाफ्रेम संगति को गति देने के लिए संख्यात्मक रूप से लाभ उठा सकते हैं।

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

"स्पीड अप" को वापस करने के लिए कोई संख्या? विशेष रूप से, क्या यह stackoverflow.com/questions/20906474/… से अधिक तेज़ है ?
ivan_pozdeev

मैं ओपी को अपने संघटन को गति देने के लिए रास्ता नहीं पूछ रहा हूं, यह सिर्फ पहले से स्वीकार किए गए उत्तर की पुनरावृत्ति जैसा दिखता है।
pydsigner

2
यदि डेटा में मिश्रित कॉलम प्रकार हैं, तो यह काम नहीं करेगा।
पिमिन कोंस्टेंटिन केफालोकोस

1
@ एसकेजी परिपूर्ण .. मेरे लिए यह एकमात्र कार्यशील समाधान है। 2 सेकंड में कुल 500 फाइलें 400k पंक्तियां। इसे पोस्ट करने के लिए धन्यवाद।
फ्रैंक सीपी

11

यदि आप पुनरावर्ती रूप से खोज करना चाहते हैं ( पायथन 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, क्योंकि यह एक सूची के बजाय एक पुनरावृत्त लौटाता है ।



संपादित करें: गुणक पुनरावर्ती कार्य:

आप उपरोक्त को मल्टीप्लेट रिकॉर्डर फ़ंक्शन (लिनक्स, विंडोज, मैक) में लपेट सकते हैं , इसलिए आप ऐसा कर सकते हैं:

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)

11

आसान और तेज

csvनामों की सूची बनाने के लिए बिना दो या अधिक आयात करें ।

import glob

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

8

एक लाइनर का उपयोग map, लेकिन अगर आप अतिरिक्त आर्ग्स निर्दिष्ट करना चाहते हैं, तो आप कर सकते हैं:

import pandas as pd
import glob
import functools

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

नोट: mapअपने आप से आपको अतिरिक्त आर्गन की आपूर्ति नहीं करने देता है।


4

यदि कई सीएसवी फाइलें ज़िप की जाती हैं, तो आप सभी को पढ़ने के लिए और नीचे के रूप में संक्षिप्त करने के लिए 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)))

4

सूची समझ के साथ एक और लाइनर जो read_csv के साथ तर्कों का उपयोग करने की अनुमति देता है।

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

3

@ सिड के अच्छे जवाब के आधार पर।

कंक्रीटिंग करने से पहले, आप 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यह आवश्यक नहीं है, लेकिन यह फाइलों के क्रम को बनाए रखेगा जो विश्लेषण के लिए उपयोगी हो सकता है।

एक शब्दकोश में सीएसवी फ़ाइलों को लोड करें। फिर संक्षिप्त करें:

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 विधियों का उपयोग कर सकते हैं ।


3

pathlibलाइब्रेरी का उपयोग कर वैकल्पिक (अक्सर पसंदीदा os.path)।

यह विधि पंडों के चलने के उपयोग से बचाती है concat()/ apped()

पंडों के प्रलेखन से:
यह ध्यान देने योग्य है कि कॉनैट () और इसलिए एपेंड ()) डेटा की एक पूरी प्रति बनाता है, और इस फ़ंक्शन का लगातार पुन: उपयोग करने से एक महत्वपूर्ण प्रदर्शन हिट हो सकता है। यदि आपको कई डेटासेट पर ऑपरेशन का उपयोग करने की आवश्यकता है, तो सूची समझ का उपयोग करें।

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 ड्राइव पर Colab का उपयोग कैसे कर सकते हैं

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)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.