学校のデータ分析の授業でやっとpandasやdataframeの基礎を学んだのでまとめてきたいと思う。これでkaggleもできるようになると思うよ!!

chapter 1

importing

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn as sl

reading csv

salary = pd.read_csv('salary.csv')

dataframe meta operation

# print first 5 rows
df.head()

# print first n rows
df.head(n)

# print shape
print(df.shape)

# print columns
print(df.columns)

# print info
print(df.info())

converting dataframe to list or numpy

# convert dataframe's columns to string list
string_list = df.columns.values

getting specific column

game_name = df['game_name']

getting dummiy of specific column (prefix is optional)

dummy_column = pd.get_dummies(df['specific_row'],prefix='pref')

slice specific row and column

# get slice of rows from 100 to 199
slieced = df.iloc[100:200,:]

# get specific columns
all_scores = ['Critic_Score', 'User_Score']
reg_sales_df = game_sales[all_scores]

# get specific clumns like specified
all_sales = game_sales.filter(like='Sales')

# get specific rows and columns
sample_info = eng_salary.loc[:11244,['Degree', 'Specialization', 'Salary']]

chapter 2 (Filtering)

filter by condition

# get rows where Year_of_Release is 2016
filter = game_sales['Year_of_Release'] ==  2016
year_of_2016 = game_sales[filter]

# get rows which satisifes the multiple condition and print specific columns
pub_is_Nintendo = game_sales['Publisher'] == 'Nintendo'
year_is_85_to_95 = (game_sales['Year_of_Release'] >= 1985) &\
                   (game_sales['Year_of_Release'] <= 1995)
Nintendo_85_to_95 = game_sales[year_is_85_to_95 & pub_is_Nintendo] 
print(Nintendo_85_to_95[['Name', 'Publisher', 'Year_of_Release']], end='\n\n')


# same as above but in one line.
sp_omit = 'information technology'
cond1 = eng_salary['Specialization'] != sp_omit
cond2 = eng_salary['English'] <= 400
cond = cond1 & cond2
output = eng_salary.loc[cond,['Specialization','English']]

grouping (IMPORTANT)

まずはgroupingがどんなことをするのかだけど、ある列について、同じものをまとめるって感じだな。そして、その列についてまあ、色々と操作をするわけです。例えば各出版社ごとの売上とかもかんたんに計算できるようになるってことです。これはクッソ便利ですよね??はい、マジで便利なんです。

# creating group by Genre
game_sales = pd.read_csv('sales.csv', encoding='CP932')
genre_groupby = game_sales.groupby('Genre')
print(genre_groupby.first().iloc[:,:4])

# get specific group's objects (in the below case it is Action)
genre_Action = genre_groupby.get_group('Action')
print(genre_Action.iloc[:,:4], end='\n\n')

# group by multiple columns and get specific row
platform_year_groupby = game_sales.groupby(['Platform','Year_of_Release'])
platform_year_14 = platform_year_groupby.get_group(('PS3',2014))

# get each groups size (The number of rows which is in the group)
state_groupby = eng_salary.groupby('CollegeState')
print(state_groupby.size() end='\n\n')


# group by multiple columns and get specific row 2
groupby_list = ['Gender', '12graduation', 'Degree']
groupby_target = ('f', 2008, 'MCA')
multi_groupby = eng_salary.groupby(groupby_list).get_group(groupby_target)

Aggregation!! (IMPORTANT!)

これはなにか?というと、グループ化したオブジェクトに対して、グループごとの統計情報を見ることが可能となる。

# group dataframe by Genre and calculate average of Critic_Score for each group
game_sales = pd.read_csv('sales.csv', encoding='CP932')
genre_groupby = game_sales.groupby(['Genre'])
genre_groupby_mean = genre_groupby.agg({'Critic_Score':'mean'})
print(genre_groupby_mean.head(), end='\n\n')

# Do the same as above. Not mean but sum
genre_plat_groupby = game_sales.groupby(['Genre', 'Platform'])
genre_plat_groupby_var = genre_plat_groupby.agg({'User_Count':'sum'})
print(genre_plat_groupby_var, end='\n\n')

# Group by multiple columns and get multiple statistics
publ_plat_groupby = game_sales.groupby(['Publisher', 'Platform'])
publ_plat_groupby_stat = publ_plat_groupby.agg({'JP_Sales':['size','median']})
print(publ_plat_groupby_stat.loc[['Nintendo','Square Enix']], end='\n\n')

# It is also possible to create your own function
plat_year_groupby = game_sales.groupby(['Year_of_Release', 'Platform'])
size_morethan_8 = lambda series: len(series > 8)
plat_year_groupby_topgame = plat_year_groupby.agg({'Critic_Score':size_morethan_8})
cols_name = {'Critic_Score':'High_Critic_Score_Total'}
plat_year_groupby_topgame = plat_year_groupby_topgame.rename(columns=cols_name)

# Group by multiple rows and calculate multiple statistics for multiple columns
gender_spec_groupby = eng_salary.groupby(['Gender','Specialization'])
agg_dict = {'Logical':['min','max'],
            'Salary':['min','max']
            }
gender_spec_minmax_salary = gender_spec_groupby.agg(agg_dict)

Concatenate, Join, Merge

これは、データベースから引っ張ってくるデータを解析するときに必須になるやつだね。まあ難しいのはわかる。inner join? いや、この辺はちょっとおいておきましょう。まあすぐにできるようになるところではない。まじでなれが必要なところだから。必要に迫られたらやるって感じにしましょう。

chapter 3

まあ、ここでは、各カラムに対して、まとめて操作できるよー!!って話をしているわけですね。あとは、自分で好きに新しいカラムを作れるよー!って話だな。

Arithmetic Operations

# calculate the mean of specific columns and create new column
eng_salary['Mean_Grade'] = (eng_salary['10percentage'] + eng_salary['12percentage'])/2

# DROPING specific clomun (IMPORTANT!!)
eng_salary = eng_salary.drop(['GraduationYear','12graduation'],axis=1)

Handling Missing Data

# get null rows
critic_score_nan = game_sales['Critic_Score'].isnull()
game_sales_criscr = game_sales[critic_score_nan]

# drop columns where na is above thresh 
game_sales = game_sales.dropna(thresh=11)

# fill NAN with value
game_sales['Rating'] = game_sales['Rating'].fillna('U')

# replace specifi value with naa
game_sales['JP_Sales'] = game_sales['JP_Sales'].replace(to_replace=0,value=float('nan'))

# fill nan with rows mean
game_sales[to_fill_mean] = game_sales[to_fill_mean].fillna(game_sales[to_fill_mean].mean())

Discretization

まあ、その列の値を4つに分けてみよう!!てかんじだね。

# 3.3.1
game_sales = pd.read_csv('sales.csv', encoding='CP932', index_col=0).dropna()
bins = [1980, 1990, 2000, 2010, 2020]
gen_labels = ["'80s", "'90s", "'00s", "'10s"]
game_sales['Generation'] = pd.cut(game_sales['Year_of_Release'], 
                                  bins, labels=gen_labels)
print(game_sales[['Year_of_Release','Generation']].head(10), end='\n\n')

# 3.3.2  5, precision=2, retbins=True
sale_labels = ["Low", "Mid", "High"]
game_sales['Global_Sales_Cat'] = pd.cut(game_sales['Global_Sales'], 3, 
                                     labels=sale_labels)
game_sales['Global_Sales_Range'] = pd.cut(game_sales['Global_Sales'],3, 
                                  precision=2)
to_print_cols = ['Global_Sales','Global_Sales_Cat', 'Global_Sales_Range']
print(game_sales[to_print_cols].head(10), end='\n\n')

# 3.3.3
sale_labels = ["Few", "Many"]
game_sales['Critic_Count_Cat'] = pd.qcut(game_sales['Global_Sales'], 2, 
                                     labels=sale_labels)
game_sales['Critic_Count_Range'] = pd.qcut(game_sales['Global_Sales'], 2, 
                                  precision=0)
to_print_cols = ['Critic_Count','Critic_Count_Cat', 'Critic_Count_Range']
print(game_sales[to_print_cols].tail(10), end='\n\n')
print(game_sales.groupby('Critic_Count_Cat').size(), end='\n\n')

statistics

aggregationとおんなじだね。ただ、もっとかんたんにかけるよって言うこと。

# 1 and 2 are same
genre_groupby = game_sales.groupby(['Genre'])
genre_groupby_mean1 = genre_groupby.agg({'Critic_Score':'mean'})
genre_groupby_mean2 = game_sales.groupby('Genre')['Critic_Score'].mean()

# 3.4.2
genre_plat_groupby = game_sales.groupby(['Genre', 'Platform'])
genre_plat_groupby_var = genre_plat_groupby.agg({'User_Count':'sum'})
genre_plat_groupby_var = game_sales.groupby(['Genre', 'Platform'])['User_Count'].sum()

# 3.4.3
publ_plat_groupby = game_sales.groupby(['Publisher', 'Platform'])
publ_plat_groupby_stat = publ_plat_groupby.agg({'JP_Sales':['size','mean']})
print(publ_plat_groupby_stat.loc[['Nintendo','Sony Computer Entertainment']], end='\n\n')

Filtering

まあいろいろありますよと!!

chapter4

introduction to matplotlb

僕は今までplt.plot() で無限に粘ってきた。しかし、複数のグラフを一発できれいに出力するとかっていうのができなかったんだよね。今回、それを学んで自分の血肉にした。

# 下のやつでポイントとなるのは、year_axisを取り出しているところ。そして、.valuesでnumpyオブジェクト?に変換しているってところ。これ、valuesをやらないとまだ、dataframeのままなんですよね。
yearly_sum = game_sales.groupby("Year_of_Release")['JP_Sales'].sum()
year_axis = yearly_sum.index.values
jp_sales_axis = yearly_sum.values
fig = plt.plot(year_axis,jp_sales_axis)
plt.show()

# ポイントは複数のグラフをプロットするためにplt.subplots(nrows,ncols)を指定していることころ
total_na_sales_yearly = game_sales.groupby("Year_of_Release")['NA_Sales'].sum()
total_eu_sales_yearly = game_sales.groupby("Year_of_Release")['EU_Sales'].sum()
total_na_sales = total_na_sales_yearly.values
total_eu_sales = total_eu_sales_yearly.values

fig, ax = plt.subplots(nrows=1, ncols=3, sharey=True, figsize=(10, 2))

ax[0].plot(year_axis,jp_sales_axis,'b--')
ax[1].plot(year_axis,total_na_sales,'k-')
ax[2].plot(year_axis,total_eu_sales,'m:')

plt.show()

ploting with pandas (IMPORTANT)

ここだね。まじで重要だと思います。dataframeからめっちゃかんたんにplotができるって話です。

# ヒストグラムを作る
game_sales['Year_of_Release'].plot(kind='hist')

advanced filtering

# isin() and between()
three_publ_bool = game_sales['Publisher'].isin(["Activision", "Electronic Arts", "Ubisoft"])
year_11_to_15 = game_sales['Year_of_Release'].between(2011,2015)

filtered_games = game_sales.loc[three_publ_bool & year_11_to_15]

Multiple Plots with Seaborn

これがめちゃめちゃ大事だね。まじで、Seabornっていうのを使うとめちゃめちゃきれいにプロットできるんですわ。groupyを勝手にやってくれるってことやな。そこがすごい。 はいはい、そんな感じで。

game_sales = pd.read_csv('sales.csv', encoding='CP932')
top_9_publ = game_sales.groupby('Publisher')['Name']\
              .count().sort_values().iloc[-9:].index.values

top_9_publ_games = game_sales['Publisher'].isin(top_9_publ) 
year_03_to_13 = game_sales['Year_of_Release'].between(2003, 2013)

filter_top_publ = game_sales[top_9_publ_games & year_03_to_13]
fig = sns.relplot(data=filter_top_publ,
                  x='Year_of_Release',
                  y='NA_Sales',
                  col='Publisher',
                  kind='line',
                  col_wrap=3)
plt.show()

additional techniques

まあ、これは覚えておいた方がいいよっていうテクニックを紹介します。

apply function

各行に対して、少し凝った特定の処理をしたい場合にはapply()が使えます。覚えておいた方がいいです。こんな感じです。

import pandas as pd

# Create a sample DataFrame
df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [5, 6, 7, 8]})

# Define a function to apply to each row
def process_row(row):
    # Perform some procedure on the row and return the result
    return row['A'] + row['B']

# Apply the function to each row and assign the result to a new column
df['C'] = df.apply(process_row, axis=1)

# Print the updated DataFrame
print(df)

まあ、例えば、ファイル名を表す列とかがあって、ファイルを読み込んで読み込んだファイルからなにか特徴量を抽出したいとか、そういったことをしたい場合にはこのファンクションが使えるってことです。