Pandas Dataframe’i Hive Tablosu olarak Hadoop’a Kaydetmek

Sıkı durun uzun bir yazı olacak! Böyle bir macera ilk defa başıma geldiğinde çok zordur bu iş diyordum ancak öyle çok korkulacak bir şey olmadığını işi yaptıktan sonra fark ettim. Şimdi nereden çıktı bu konu? Ben veri temizliği için Pandas’ı çok seviyorum. Büyük veri setlerinin temizlemek istediğim yerlerini koparıp Pandas ile temizleyip tekrar yerine koyuyorum.

Peki aşağıdaki serüveni nasıl bir ortamda gerçekleştirdim? Ben 4 sunuculu Hadoop cluster kullanıyorum. Hadoop dağıtımım Cloudera (CDH 5.8.4), Spark 1.6.0, Python 2.6.6, kod geliştirme ortamı olarak Jupyter, dil olarak PySpark, ana bilgisayar Windows 10. Şimdi yapacağımız iş şu: imdb_ratings veri setimizi (Pandas Dataframe(DF)) alıp önce Spark DF’e çevireceğiz, sonra bu Spark DF’i Hive tablosu olarak HDFS’e yazdıracağız ve en son olarak Jupyter’de Hive tablosuna kaydettiğimiz bu tabloyu çağırıp SparkDF’e aktaracağız.

IMDB Ratings Veri Setini İndirme

import pandas as pd
filmListesiPandasDF = pd.read_csv("http://www.datascience.istanbul/data/imdbratings.data")
filmListesiPandasDF.head()
star_rating title content_rating genre duration actors_list
0 9.3 The Shawshank Redemption R Crime 142 [u’Tim Robbins’, u’Morgan Freeman’, u’Bob Gunt…
1 9.2 The Godfather R Crime 175 [u’Marlon Brando’, u’Al Pacino’, u’James Caan’]
2 9.1 The Godfather: Part II R Crime 200 [u’Al Pacino’, u’Robert De Niro’, u’Robert Duv…
3 9.0 The Dark Knight PG-13 Action 152 [u’Christian Bale’, u’Heath Ledger’, u’Aaron E…
4 8.9 Pulp Fiction R Crime 154 [u’John Travolta’, u’Uma Thurman’, u’Samuel L….

Pandas DF Veri Türlerini Kontrol Etme

Pandas DF’i Spark DF’e çevirmeden önce info() metoduyla Pandas DF veri tiplerine göz atalım. Buradan bir şey anlamamız gerekmiyor. Sadece Spark ile Pandas veri tipleri farklı olduğu için Pandas-Spark dönüşümünden önce Pandas DF veri tiplerinin hepsini astype(str) metoduyla stringe dönüştürmekte fayda var. Aksi halde hata alabiliriz.

filmListesiPandasDF.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 979 entries, 0 to 978
Data columns (total 6 columns):
star_rating       979 non-null float64
title             979 non-null object
content_rating    976 non-null object
genre             979 non-null object
duration          979 non-null int64
actors_list       979 non-null object
dtypes: float64(1), int64(1), object(4)
memory usage: 46.0+ KB

Pandas DF Veri Türlerini Dönüştürme

filmListesiPandasDF[['star_rating','title','content_rating','genre','duration','actors_list']] = filmListesiPandasDF[['star_rating','title','content_rating','genre','duration','actors_list']].astype(str)
filmListesiPandasDF.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 979 entries, 0 to 978
Data columns (total 6 columns):
star_rating       979 non-null object
title             979 non-null object
content_rating    979 non-null object
genre             979 non-null object
duration          979 non-null object
actors_list       979 non-null object
dtypes: object(6)
memory usage: 46.0+ KB

Gördüğümüz gibi float ve integer gitti hepsi object oldu. Şimdi SparkDF oluşturalım.

filmListesiSparkDF = sqlContext.createDataFrame(filmListesiPandasDF)
type(filmListesiSparkDF)
pyspark.sql.dataframe.DataFrame

Yeni SparkDF’in şemasını yazdıralım:

filmListesiSparkDF.printSchema()
root
 |-- star_rating: string (nullable = true)
 |-- title: string (nullable = true)
 |-- content_rating: string (nullable = true)
 |-- genre: string (nullable = true)
 |-- duration: string (nullable = true)
 |-- actors_list: string (nullable = true)

Yukarıda gördüğümüz gibi her şey string. Bu şekilde Hive tablosuna kaydedeceğiz. Daha sonra hive tablosunda tekrar integer ve float türlerini ALTER TABLE komutuyla eski haline getireceğiz.

Spark DF’i Geçici Tablo Olarak Kaydetme

Hive tablosu olarak kaydetmeden önce SparkDF’i geçici tablo olarak kaydetmeliyiz.

filmListesiSparkDF.registerTempTable('imdbratings')
sqlContext.sql("create table imdbratings_hive_table as select * from imdbratings")

Hive’e Girip Kaydettiğimiz Tabloyu Kontrol Etme ve Biraz Veri Mıncıklama

beeline -u jdbc:hive2://namenode:10000 komutuyla Hive’e erişiyorum. Yakın zamana kadar belki hala Hive’e hive komutuyla erişilebiliyordu ancak hive komutu artık kullanılmayacak (deprecated). Neyse Hive ile ilgili ayrı bir yazı oluşturacak kadar malzeme çıkar buradan kısa kesiyorum. Hive açıldığında karşımıza şu çıkar:

Buraya show tables; komutunu yazarız ve Hive bize varsayılan veri tabanındaki (default database) tabloları listeler.

Biz en son tablomuzu imdbratings_hive_table olarak kaydetmiştik, yukarıdaki fotoğrafta gördüğümüz gibi aynı isimle tablo yerini almış. Şimdi basit bir kaç sorguyla tablo içi dolu mu yoksa sadece adı mı burada bakalım. Mesela satır sayısını bulalım. Komut:select count(*) as satir_sayisi from imdbratings_hive_table;

describe imdbratings_hive_table; komutuyla tablo yapısını inceleyelim:

Yukarıda gördüğümüz gibi tüm veri türlerimiz string türünde. Şimdi orjinal verimizde star_rating float, duration ise integer idi. Biz hive üzerinde bunları eski haline döndürelim. Komutlarımız sırasıyla:

alter table imdbratings_hive_table change star_rating star_rating float; 
alter table imdbratings_hive_table change duration duration int;

Yalnız şunu unutmayalım bu komutlar disk üzerindeki veriyi değil, hive tablosunun metadatasını (şema) değiştirir. Sonucu tekrar describe ile görelim:

Evet star_rating float, duration ise integer olmuş.

Hive Tablosunu Spark’a Dataframe Olarak Alma

Şimdi ana bellekteki Pandas DF’i taa HDFS’e Hive tablosu olarak kaydettik ve verimizi sağlama aldık (amma sağlamcı milletiz ha 🙂 ). Buradan tekrar Spark ortamına veriyi çıkarıp her türlü işlemi yapabiliriz. Tekrar Jupyter Notebook’a geliyoruz.

imdbratingsHiveTabletoSparkDF = sqlContext.sql("select * from imdbratings_hive_table")
+-----------+--------------------+--------------+------+--------+--------------------+
|star_rating|               title|content_rating| genre|duration|         actors_list|
+-----------+--------------------+--------------+------+--------+--------------------+
|        9.3|The Shawshank Red...|             R| Crime|     142|[u'Tim Robbins', ...|
|        9.2|       The Godfather|             R| Crime|     175|[u'Marlon Brando'...|
|        9.1|The Godfather: Pa...|             R| Crime|     200|[u'Al Pacino', u'...|
|        9.0|     The Dark Knight|         PG-13|Action|     152|[u'Christian Bale...|
|        8.9|        Pulp Fiction|             R| Crime|     154|[u'John Travolta'...|
+-----------+--------------------+--------------+------+--------+--------------------+
only showing top 5 rows

Eveet yolun sonuna geldik. Amma uzun bir yazı oldu, Jules Verne’nin 80 Günde Devri Alem’ini geçti 🙂 Başka bir yazıda buluşmak dileğiyle, veriyle kalın…

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir