Project

Python / DASK(2) - use case : 불러오기, 인덱싱

0. DASK로 불러올 때 ValueError가 발생한다면

지난 글에서도 썼지만, 기본적으로 DASK는 Pandas에서 csv를 불러오는 방식과 동일하다. 

#읽어오기
example = dd.read_csv("example.csv")

 

그런데 이게 가끔 안될 때가 있다. 정확히 말하자면, .read_csv()로 다스크 데이터프레임을 만드는 것까지는 가능하지만, 이 데이터를 불러오거나 처리하려거나 하면 ValueError가 발생한다.   

처음 이 에러를 접했을 땐 정말 ...?였다. 데이터프레임을 읽을 수도 없다고?

 

 

에러 메시지를 읽어보면 DASK가 읽어온 데이터 타입과 실제 데이터프레임의 데이터 타입이 다를 때 이 에러가 발생하는 것 같다. (왜 다르냐고 묻고 싶지만...) 다행히 다스크는 독스트링(docstring)이나 에러 메시지가 굉장히 친절하고 상세하다. 아래 에러 메시지에서도 이렇게 추가해주면 아마 괜찮을걸? 하면서 문제가 발생한 column은 물론, 심지어 어떻게 고치면 좋을지까지 알려주고 있다. 

ValueError: Mismatched dtypes found in `pd.read_csv`/`pd.read_table`.

+-------------------+---------+----------+
| Column            | Found   | Expected |
+-------------------+---------+----------+
| getoff_datetime   | float64 | int64    |
| getoff_station_id | float64 | int64    |
+-------------------+---------+----------+

Usually this is due to dask's dtype inference failing, and
*may* be fixed by specifying dtypes manually by adding:

dtype={'getoff_datetime': 'float64',
       'getoff_station_id': 'float64'}

to the call to `read_csv`/`read_table`.

Alternatively, provide `assume_missing=True` to interpret
all unspecified integer columns as floats.

 

그러니 위의 에러가 발생한다면 아래처럼 다스크의 조언을 따르도록 하자. 그럼 정상적으로 데이터프레임을 불러올 수 있다. 

#다시 읽어오기
example = dd.read_csv("example.csv", dtype={'getoff_datetime': 'float64','getoff_station_id': 'float64'})

 


 

1. DASK에서의 indexing은 Pandas와는 다르다 

1-1. .loc

Pandas의 기초는 indexing이라고 해도 과언이 아닐 것이다. 예를 들어 df.loc["(row명)"] 은 해당 이름을 가진 row를 불러온다.  

예시는 제주도 버스 정류장 데이터

 

DASK에서는 인덱싱한 데이터를 보고 싶다면 .compute()를 해주어야 한다. 그렇지 않으면 또 다스크 데이터프레임 구조만 보여준다. 

example_dd.loc[0].compute()

.compute()를 하지 않았을 때

 

그런데 .compute()를 해보면 인덱스가 0인 row가 123개나 된다. 위의 이미지를 자세히보면, npartitions가 123개인 것을 확인할 수 있다. 현재 DASK 데이터프레임에는 123개의 조각(partition)들이 있고, 각 조각마다 따로 index가 붙기 때문에 모든 조각들의 인덱스 0 row가 인덱싱된 것이다. 그러니 partition의 수와 인덱스가 0인 row의 수가 같다.  

범위로 인덱싱 했을 때에도 마찬가지다. 0번부터 4번까지의 row가 123개씩 있기 때문에, 전체 row의 수는 5개 * 123개로 615개다. 이 점에만 유의한다면 .loc 의 사용은 판다스에서와 거의 유사하다고 생각된다. 

 

1-2. .iloc

판다스의 데이터프레임은 .iloc을 통해서, 몇번째 row/column인지를 지정해 인덱싱할 수 있다. 아래는 0번째~4번째의 row와 0번째~4번째의 column을 인덱싱해온 예시다.  

저장할 때 index=False를 안했네... 머쓱

 

그런데 다스크 데이터프레임인 경우 판다스 데이터프레임에서처럼 동작하지 않는다. 원하는 대로 동작하지 않을 뿐더러 아예 에러가 난다. 에러 메시지는 다음과 같다.

"DataFrame.iloc' only supports selecting columns. It must be used like 'df.iloc[:, column_indexer]"

즉, 다스크 데이터프레임에서는 iloc일 경우 row의 범위는 지정할 수 없고, column의 범위만 지정할 수 있다. 

아래와 같이 row는 전체 범위로 두고, column 범위만 지정하는 것은 작동한다. 역시 다스크는 까다로운 친구다. 대체로 다스크에서 동작하지 않는 것은 몇번째인지, 몇개인지, 즉 개수와 관련된 메서드들이다. 

이건 된다