여러 CSV 파일을 팬더로 가져오고 하나의 DataFrame으로 연결


403

디렉토리에서 팬더로 여러 CSV 파일을 읽고 하나의 큰 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 루프 내에서 도움이 필요하십니까 ???


dfs목록에 추가하지 않기 때문에 코드는 아무 것도 수행하지 않습니다 . 행 data = pd.read_csv(filename)을 로 바꾸고 싶지 않습니다 dfs.append(pd.read_csv(filename). 그런 다음 목록을 반복해야하며의 목록에서 작동 concat하지 않을 것이라고 생각 합니다. concatdf
EdChum

또한 마지막 줄에서 모듈 이름과 모듈의 별명을 혼합하고 있지 않아야 big_frame = pd.concat(dfs, ignore_index=True)합니까? 어쨌든 데이터 프레임 목록이 있으면 목록을 반복하여 연결해야합니다.big_frame
EdChum

예, 코드를 편집 할 수 있지만 나는이에 좀 더 도움이 필요 그래서 파이썬에 새로운 해요, 여전히 CSV - 파일에서 연결된 dataframe을 구축 할 수 아니에요
조나스

dfs지금 반복해야 하므로 for df in dfs: big_frame.concat(df, ignore_index=True)작동해야합니다 . append대신 시도해 concat도됩니다.
EdChum

작동하지 않는 것을 더 정확하게 말할 수 있습니까? 때문에이 concat잘 당신이했던 것처럼 DataFrames의 목록을 처리해야합니다. 나는 이것이 매우 좋은 접근법이라고 생각합니다.
joris

답변:


455

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

이것은 일을하는 구식 일명 수동 방법 인 것처럼 보입니다. Hapood 생태계는 하나의 데이터 소스 인 것처럼 다른 파일 형식 (csv, json, txt, 데이터베이스)을 포함하는 여러 다른 디렉토리에서 직접 SQL 쿼리를 수행 할 수있는 도구 목록이 늘어나고 있습니다. "큰 데이터"를 수행하는 데 20 년이 걸렸기 때문에 파이썬에도 비슷한 것이 있어야합니다.
Hexatonic

275
똑같은 것이 더 간결하고 아마도 목록을 사용하지 않기 때문에 더 빠를 df = pd.concat((pd.read_csv(f) for f in all_files)) 수도 있습니다 . 또한 os.path.join(path, "*.csv")대신에를 사용해야 path + "/*.csv"하므로 OS 독립적입니다.
Sid

4
이 답변을 사용하면 파일 이름 df['filename'] = os.path.basename(file_)이 예인 for file_ loop 와 같이 새 열을 추가 할 수있었습니다 . Sid의 답변이 허용하는지 확실하지 않습니까?
curtisp

4
@curtisp 당신은 여전히 ​​Sid의 대답으로 그렇게 할 수 있습니다 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
@Mike @Sid 마지막 두 줄은 다음으로 바꿀 수 있습니다 pd.concat((pd.read_csv(f) for f in all_files), ignore_index=True). 내부 괄호는 Pandas 버전 0.18.1
Igor Fobia

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 인수가 필요하지 않은 경우 특히 유용합니다!
rafaelvalle

15
반면에 논쟁이 필요한 경우 람다로이를 수행 할 수 있습니다.df = pd.concat(map(lambda file: pd.read_csv(file, delim_whitespace=True), data_files))
fiedl

^ 또는 with 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 데이터 프레임은 Pandas 데이터 프레임 API의 하위 집합을 구현합니다. 모든 데이터가 메모리에 맞는 경우 호출df.compute() 하여 데이터 프레임을 Pandas 데이터 프레임으로 변환 할 수 있습니다 .


30

여기의 거의 모든 답변은 불필요하게 복잡하거나 (글로브 패턴 일치) 추가 타사 라이브러리에 의존합니다. 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. 파이썬의 맵 (함수, 반복 가능) 은 함수 (the pd.read_csv())에게 파일 경로의 모든 csv 요소 인 반복 가능 (우리 목록)을 보냅니다 .
  2. Panda의 read_csv () 함수는 각 CSV 파일을 정상적으로 읽습니다.
  3. Panda의 concat () 은이 모든 것을 하나의 df 변수로 가져옵니다.

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에 갔다 . 그러나 최근에 numpy를 사용하여 조작을 수행하고 반복적으로 데이터 프레임 자체를 조작하는 대신 데이터 프레임에 한 번 할당하는 것이 더 빠르다는 사실을 알게되었습니다.이 솔루션에서도 작동하는 것 같습니다.

이 페이지를 방문하는 사람이이 접근법을 고려하기를 진심으로 원하지만이 거대한 코드를 주석으로 첨부하여 읽기 어렵게 만들고 싶지는 않습니다.

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

"속도 향상"을 뒷받침 할 숫자가 있습니까? 특히 stackoverflow.com/questions/20906474/… 보다 빠릅니다 .
ivan_pozdeev

OP가 연결 속도를 높이는 방법을 요구하는 것을 보지 못했습니다. 이것은 기존의 승인 된 답변의 재 작업처럼 보입니다.
pydsigner

2
데이터에 열 유형이 혼합되어 있으면 작동하지 않습니다.
Pimin Konstantin Kefaloukos

1
@ SKG perfect .. 이것은 나를 위해 유일하게 작동하는 솔루션입니다. 500 개의 파일 400k 행이 총 2 초에 발생합니다. 게시 해 주셔서 감사합니다.
FrankC

11

재귀 적 으로 검색 하려면 ( 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)

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

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

read_csv와 함께 인수를 사용할 수있는 목록 이해 기능을 갖춘 또 다른 라이너.

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

3

@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 메소드를 사용하여 사전의 키 크기를 관련있는 작은 부분으로 만 줄일 수 있습니다.


3

pathlib라이브러리를 사용하는 대안 (종종 선호 os.path).

이 방법은 pandas 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)

-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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.