반응형

Consuming CSV data

 

CSV 파일 포멧은 plain 텍스트로 테이블 형태의 데이터를 저장하는 자주 사용되는 포멧이다.

 

아래 예제는 타이타닉 데이터셋을 로드하여 csv 포멧으로 읽는 것을 보여준다.

titanic_file = tf.keras.utils.get_file("train.csv", "https://storage.googleapis.com/tf-datasets/titanic/train.csv") 

df = pd.read_csv(titanic_file, index_col=None) df.head() 

 

  survived sex age n_siblings_spouses parch fare class deck embark_town alone
0 0 male 22.0 1 1 0 7.2500 Third Southampton n
1 1 female 38.0 1 1 0 71.2833  First Cherbourg n
2 1 female 26.0 0 0 0 7.9250  Third Southampton y
3 1 female 35.0 1 1 0 53.1000  First Southampton n
4 0 male 28.0 0 0 0 8.4583 Third Cherbourg y

 

데이터가 메모리에 로딩 가능하다면, Dataset.from_tensor_slices method는 디렉토리에서 도작하고 이 데이터가 쉽게 import되어지게 한다.

titanic_slices = tf.data.Dataset.from_tensor_slices(dict(df))  

for feature_batch in titanic_slices.take(1):   
    for key, value in feature_batch.items():     
        print("  {!r:20s}: {}".format(key, value)) 

>>> print문 내 {!r:20s}에서 !r은 작은 따옴표(')를 출력하게 함.

'survived'          : 0  
'
sex'               : b'male'
  
'
age'               : 22.0
  
'
n_siblings_spouses': 1
  
'
parch'             : 0
  
'
fare'              : 7.25
  
'
class'             : b'Third'
  
'
deck'              : b'unknown'
  
'
embark_town'       : b'Southampton'
  
'
alone'             : b'n'
 

위 방법보다 더 유연한 접근 방법은 필요시 디스크로부터 데이터를 로드하는 것이다.

 

tf.data 모듈은 RFC 4180 (CSV 파일 규격) 을 따르는 하나이상의 CSV 파일에서 레코드를 추출하기 위한 방법을 제공한다.

 

experimental.make_csv_dataset 함수는 CSV 파일을 읽기위한 고수준 인터페이스이다. 이것은 간단한 사용을 위해 batch, shuffle같은 다른 많은 특성과 column type 추론(inference)를 지원한다.

titanic_batches = tf.data.experimental.make_csv_dataset(titanic_file, batch_size=4, label_name="survived")  

for feature_batch, label_batch in titanic_batches.take(1):
    print("'survived': {}".format(label_batch))   
    print("features:")   
    for key, value in feature_batch.items():     
        print("  {!r:20s}: {}".format(key, value)) 

 

'survived': [1 0 0 0] 
features:  
'
sex'               : [b'male' b'male' b'male' b'male']
  
'
age'               : [25. 28. 31. 47.]
  
'
n_siblings_spouses': [1 0 1 0]
  
'
parch'             : [0 0 1 0]
  
'
fare'              : [ 7.775   9.5    37.0042 34.0208]
  
'
class'             : [b'Third' b'Third' b'Second' b'First']
  
'
deck'              : [b'unknown' b'unknown' b'unknown' b'D']
  
'
embark_town'       : [b'Southampton' b'Southampton' b'Cherbourg' b'Southampton']
  
'
alone'             : [b'n' b'y' b'n' b'y']
 

 

만약 데이터셋의 일부 서브셋만이 필요하다면, select_columns를 사용하면 된다.

titanic_batches = tf.data.experimental.make_csv_dataset(titanic_file, batch_size=4,
                                                                  label_name="survived", select_columns=['class', 'fare', 'survived']) 

 

for feature_batch, label_batch in titanic_batches.take(1):      
    print("'survived': {}".format(label_batch))   
    for key, value in feature_batch.items():     
        print("  {!r:20s}: {}".format(key, value)) 

 

'survived': [0 1 0 1]  
'
fare'              : [ 7.2292 53.1    27.7208 20.575 ]
  
'
class'             : [b'Third' b'First' b'Second' b'Third']
 

 

더 세부적으로 제어할 수 있는 저수준의 experimental.CsvDataset도 있다. 이것은 column 타입 추론을 제공하지 않아 각 컬럼의 타입을 명시해야 한다.

titanic_types  = [tf.int32, tf.string, tf.float32, tf.int32, tf.int32, tf.float32, tf.string, tf.string, tf.string, tf.string]  
dataset = tf.data.experimental.CsvDataset(titanic_file, titanic_types , header=True)  

for line in dataset.take(10):   
    print([item.numpy() for item in line]) 

 

[0, b'male', 22.0, 1, 0, 7.25, b'Third', b'unknown', b'Southampton', b'n'] 
[1, b'female', 38.0, 1, 0, 71.2833, b'First', b'C', b'Cherbourg', b'n'] 
[1, b'female', 26.0, 0, 0, 7.925, b'Third', b'unknown', b'Southampton', b'y'] 
[1, b'female', 35.0, 1, 0, 53.1, b'First', b'C', b'Southampton', b'n'] 
[0, b'male', 28.0, 0, 0, 8.4583, b'Third', b'unknown', b'Queenstown', b'y'] 
[0, b'male', 2.0, 3, 1, 21.075, b'Third', b'unknown', b'Southampton', b'n'] 
[1, b'female', 27.0, 0, 2, 11.1333, b'Third', b'unknown', b'Southampton', b'n'] 
[1, b'female', 14.0, 1, 0, 30.0708, b'Second', b'unknown', b'Cherbourg', b'n'] 
[1, b'female', 4.0, 1, 1, 16.7, b'Third', b'G', b'Southampton', b'n'] 
[0, b'male', 20.0, 0, 0, 8.05, b'Third', b'unknown', b'Southampton', b'y'] 

만약 데이터셋의 일부 컬럼의 값이 비어있다면, CsvDataset 인터페이스는 컬럼의 타입 대신 기본값을 설정할 수 있다.

 

우선 테스트 CSV 파일을 작성한다.

%%writefile missing.csv 
1,2,3,4 
,2,3,4 
1,,3,4 
1,2,,4 
1,2,3, 
,,, 

 

Writing missing.csv   

 

# Creates a dataset that reads all of the records from two CSV files, each with 
# four float columns which may have missing values.  

record_defaults = [999,999,999,999] 
dataset = tf.data.experimental.CsvDataset("missing.csv", record_defaults) 
dataset = dataset.map(lambda *items: tf.stack(items)) 
dataset 

 

<MapDataset shapes: (4,), types: tf.int32 

 

for line in dataset:  
    print(line.numpy()) 

 

[1 2 3 4] 
[999   2   3   4] 
[  1 999   3   4] 
[  1   2 999   4] 
[  1   2   3 999] 
[999 999 999 999] 

 

기본적으로 CsvDataset은 파일의 각 라인에 대한 각 컬럼을 모두 만든다. 하지만, 헤드라인으로 시작하거나, 몇몇 불필요한 컬럼이 포함된 경우, 라인과 컬럼을 각각 header와 select_cols 인자로 제거할 수 있다.

# Creates a dataset that reads all of the records from two CSV files with 
# headers, extracting float data from columns 2 and 4. 

record_defaults = [999, 999] # Only provide defaults for the selected columns 
dataset = tf.data.experimental.CsvDataset("missing.csv", record_defaults, select_cols=[1, 3]) 
dataset = dataset.map(lambda *items: tf.stack(items)) 

dataset 

 

<MapDataset shapes: (2,), types: tf.int32> 

 

for line in dataset:      
    print(line.numpy()) 

 

[2 4] 
[2 4] 
[999   4] 
[2 4] 
[  2 999] 
[999 999] 

 

반응형

+ Recent posts