유승훈

Python(4) - glob, listdir 본문

languages/Python

Python(4) - glob, listdir

seunghuni96 2020. 3. 17. 19:19

앞서 올린 글 (Python - Concat)과 이어지는 강의내용입니다.

 

1. glob

 

여러 데이터를 하나의 데이터로 만들려면, 병합하기 전에 python에 로드된 상태여야 합니다. 데이터가 비교적 적을때에는 하나하나 불러오는 코드를 작성하는게 불편하지 않으나, 10개 100개가 되면 각각의 파일을 불러오는 코드를 작성하는게 쉽지않습니다. 그때 glob을 사용합니다. 파일명의 패턴을 매치시켜 읽어오는 방식입니다.

 

여기서 *나 ?를 여러 파일을 한꺼번에 지정하는 용도로 활용할수있습니다. 정규표현식에 대해서 알고있거나 활용해봤다면 이해가 쉬울것같습니다. 이런 문자들을 Wildcard Character. 와일드카드 문자라고 합니다.

  • *는 전체를 의미합니다. '*.csv"라고 하면 해당 경로에 있는 모든 csv 파일들을 의미합니다.

  • ?는 모든 문자를 의미합니다. 'file_?.csv'라고 하면 "file_아무 한글자"로 된 csv 파일들을 의미합니다.

이렇게 표현식의 형태로 glob에 넣어서 실행하면, 해당 패턴과 일치하는 파일명을 리스트로 반환합니다. 때문에 앞서 공부했던 concat 함수에 바로 넣어줄수있습니다. 

 

globbing 폴더에 파일을 넣어뒀습니다.

이런식으로 한 폴더에 파일을 넣어뒀습니다. 스파이인 df1을 제외하고는 전부 박스오피스 파일입니다. glob으로 어떻게 내가 원하는 파일만 가져올수있는지 보겠습니다.

 

# glob *.*
glob.glob('C:/Users/rsh15/Desktop/seunghuni/globbing/*.*')
['C:/Users/rsh15/Desktop/seunghuni/globbing\\df1.csv',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (1).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (10).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (2).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (3).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (4).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (5).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (6).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (7).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (8).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (9).xlsx']


# glob *.file
glob.glob('C:/Users/rsh15/Desktop/seunghuni/globbing/*.csv')
['C:/Users/rsh15/Desktop/seunghuni/globbing\\df1.csv']

glob.glob('C:/Users/rsh15/Desktop/seunghuni/globbing/*.xlsx')
['C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (1).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (10).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (2).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (3).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (4).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (5).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (6).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (7).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (8).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (9).xlsx']

glob.glob('C:/Users/rsh15/Desktop/seunghuni/globbing/*')
['C:/Users/rsh15/Desktop/seunghuni/globbing\\df1.csv',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (1).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (10).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (2).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (3).xlsx', 
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (4).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (5).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (6).xlsx', 
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (7).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (8).xlsx',
'C:/Users/rsh15/Desktop/seunghuni/globbing\\주간_주말_박스오피스_2018-05-25 (9).xlsx']


# glob using ?
glob.glob('C:/Users/rsh15/Desktop/seunghuni/globbing/df?.csv')
['C:/Users/rsh15/Desktop/seunghuni/globbing\\df1.csv']

 

glob에서 wildcard character인 ?나 *를 활용해서 원하는 데이터만 리스트 형태로 가져왔습니다. 먼저 *.*를 보면 globbing 폴더에 있는 모든 파일의 경로를 리스트로 가져오는 것을 볼수있습니다. *도 동일하게 모든 데이터를 의미하는데요, 차이는 *.*는 뒤에 .csv나 .xlsx등의 파일 확장자를 이어줄수없지만 *는 *.csv, *.xlsx 처럼 파일 확장자를 이어서 원하는 파일형식을 취하는 데이터만 가져온다는 것입니다. ?는 모든 문자를 의미하기 때문에 df?를 넣어줬을때 파일 중 df1.csv만 가져오는것을 볼수있습니다.

df_list = glob.glob('C:/Users/rsh15/Desktop/seunghuni/globbing/*.xlsx')

df_bind = [] # 빈 리스트를 먼저 만들고 - 데이터 저장용
df_shape = [] # 빈 리스트를 하나 더 - 데이터별 행 길이 저장용

for k in df_list: # glob의 결과 리스트로 loop
     a = pd.read_excel(k,skiprows=range(0,3))
     a = a[1:a.shape[0]] # 간단한 전처리를 한 뒤
     df_bind.append(a) # df_bind에 읽어온 데이터를 추가하고

     b = a.shape[0] # shape정보를 뽑아서
     df_shape.append(b) # df_shape에 저정한다.

df_final = pd.concat(df_bind,axis=0)
df_final.shape
(11575, 17)

sum(df_shape)
11575

이렇게 glob한 결과로 얻은 파일명 리스트로 loop를 돌리면 여러개의 데이터를 한번에 불러 리스트에 넣을수있습니다. 리스트에 있는 데이터들을 합쳐서 한번에 전처리를 할수도 있고, 전처리를 한 후에 합칠수도 있습니다.

 

for loop를 돌려 만든 df_bind

짧은 코드로 사진과 같이 df_bind 리스트를 만들었습니다. 10개의 데이터가 한 리스트 안에 차곡차곡 불러와져있는것을 볼수있습니다. for문을 돌릴때 읽어온 각 데이터의 행 길이를 저장하여 합친것과 불러온 모든 데이터를 합친 행의 길이가 동일한것을 확인할수있습니다. 이런식으로 여러개의 데이터를 불러올때 glob을 활용할수있습니다. 비슷한 역할을 하는 함수로는 os의 listidir이 있습니다.

 

2. listdir

 

경로에 있는 모든 파일들을 가져오는 함수로 glob 말고도 os의 listdir이 있습니다.

 

aa = os.listdir('C:/Users/rsh15/Desktop/seunghuni/globbing/')

bb = [k for k in aa if k.endswith('.xlsx')]
['주간_주말_박스오피스_2018-05-25 (1).xlsx',
'주간_주말_박스오피스_2018-05-25 (10).xlsx',
'주간_주말_박스오피스_2018-05-25 (2).xlsx',
'주간_주말_박스오피스_2018-05-25 (3).xlsx',
'주간_주말_박스오피스_2018-05-25 (4).xlsx',
'주간_주말_박스오피스_2018-05-25 (5).xlsx',
'주간_주말_박스오피스_2018-05-25 (6).xlsx',
'주간_주말_박스오피스_2018-05-25 (7).xlsx',
'주간_주말_박스오피스_2018-05-25 (8).xlsx',
'주간_주말_박스오피스_2018-05-25 (9).xlsx']

dd = [j for j in aa if j.startswith('df')]
['df1.csv']

가장 큰 차이점은 listdir은 경로에 들어있는 파일들의 이름을 가져오면서 조건을 설정할수없다는 것입니다. *,? 등의 문자를 써서 원하는 파일만 가져올수있는 glob과는 다릅니다. 따라서 일단 해당 경로에 있는 모든 파일들의 이름을 가져온 후에 endswith, startswith등의 전처리 과정을 거쳐 원하는 파일명만 남도록 처리해주어야 합니다. 위의 예시처럼 .xlsx로 끝나는 파일들만 가져온것을 참고하면 이해가 쉬울것같습니다. df1 데이터의 경우에는 df로 시작하는 파일들을 전부 읽어온다는 생각으로 startswith('df")를 작성했습니다. 결과를 보면 위에서 glob을 쓸때 경로에 넣어주었던 파일 필터링과 크게 다르지 않다는 것을 볼수있습니다.

 

다른 차이점으로는 glob은 파일의 최상위 경로까지 모두 가져오는 반면, listdir은 딱 파일명만 가져온다는 점입니다. 같은 os에 있는 chdir로 기본 경로를 변경해주었다면 파일명만 넣었을때 알아서 데이터를 읽어오지만, 그렇지 않다면 glob으로 가져온, 최상위 경로까지 있는 것을 사용하는 것이 오류가 날 확률을 낮춰주는 방법이 아닐까 생각합니다.

 

이렇게 경로에 있는 파일들의 목록을 가져오는 glob과 listdir을 보았습니다. 큰 역할은 같아도 세부적인 결과가 다르니 상황에 따라, 혹은 익숙한 함수를 써서 여러 파일들을 귀찮지 않고 한번에 불러오는 것을 알고있다면 나중에 데이터 읽어오는데에서 막히지 않고 작업할수있을것같습니다.

Comments