web-dev-qa-db-ja.com

複数のcsvファイルをパンダにインポートして1つのDataFrameに連結する

ディレクトリからいくつかのcsvファイルをパンダに読み込み、それらを1つの大きな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ループ内でいくつかの助けが必要だと思いますか???

253
jonas

すべてのcsvファイルに同じ列がある場合は、以下のコードを試すことができます。 csvの最初の行を列名として割り当てることができるようにheader=0を追加しました。

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)
288
Gaurav Singh

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
216
Sid
import glob, os    
df = pd.concat(map(pd.read_csv, glob.glob(os.path.join('', "my_files*.csv"))))
40

Daskライブラリは複数のファイルからデータフレームを読み込むことができます。

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

(出典: http://dask.pydata.org/en/latest/examples/dataframe-csv.html

Daskデータフレームは、PandasデータフレームAPIのサブセットを実装しています。すべてのデータがメモリに収まる場合は、 df.compute() を呼び出してデータフレームをPandasデータフレームに変換できます。

13

編集:私は https://stackoverflow.com/a/21232849/186078 に私の方法をグーグルしました。ただし最近では、データフレーム自体を反復的に操作するのではなく、numpyを使用してデータフレームに1回割り当てることが、より速いことがわかりました。

このページにアクセスしている人にこのアプローチを検討してもらいたいのですが、この巨大なコードをコメントとして添付して読みにくくしたくないと思います。

あなたはデータフレーム連結を本当にスピードアップするためにあなたはnumpyを利用することができます。

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

ここでの答えのほとんどすべては、不必要に複雑(グロブパターンマッチング)であるか、追加のサードパーティライブラリに依存しています。 Pandasとpython(すべてのバージョン)がすでに組み込まれているものすべてを使用して、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. Pythonのmap(function、iterable) (ファイルパス内のすべてのcsv要素であるiterable(私たちのリスト))を関数(pd.read_csv())に送ります。
  2. Pandaの read_csv() 関数は通常通り各CSVファイルを読み込みます。
  3. Pandaの concat() はこれらすべてを1つのdf変数にまとめます。
9
robmsmt

再帰的に検索したい場合 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)

最後の3行は1つの 単一行 で表すことができることに注意してください。

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
toto_tico

複数の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)))
4
Nim J

@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 メソッドを使用して、ディクショナリ内のキーのサイズを小さい部分のみに減らすこともできます。それは関連しています。

2
Paul Rougieux

私はこの方法がとてもエレガントだと感じました。

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

1つのライナーで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 beそれ自体では、追加の引数を指定することはできません。

1
muon

Read_csvで引数を使用することを可能にするリスト内包表記のもう1つのオンライナー。

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

簡単で速い

名前のリストを作成せずに、2つ以上のcsvをインポートします。

import glob

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