Python 「PandasのDataFrame・Series」,「numpyのndarray」,「list」の違い

'22/05/01更新:

 本記事では、Pythonでデータ処理するために、ほぼ必須のPandasとNumpyとlistについて、その概要説明と雛形コードを載せました。それぞれの特徴を一言で述べると、pandasは行列データの加工が容易、numpyは行列計算が高速、listは1次元配列でループ処理することが主な使用方法です。

 下記のような行列データを元に、それぞれのデータの見え方を説明しています。

NAME,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
cabbage,14,3,71,13,21,2,79,30,27,10,367,
carrot,14,4,77,4,23,2,83,26,25,9,370,
corn,14,5,86,10,17,1,99,29,27,8,404,
cucumber,14,4,68,5,45,4,73,28,25,8,360,
eggplant,14,4,85,6,32,9,54,34,31,6,399,
green onion,13,5,69,11,31,6,95,33,31,6,381,
green soybean,13,4,74,6,25,1,79,28,26,6,346,
iceberg lettuce,34,2,28,4,19,1,37,10,10,6,152,
japanese radish,13,7,79,7,13,3,69,33,33,5,343,
pumpkin,19,0,25,0,15,0,25,11,10,5,141,3
tomato,11,2,61,6,19,5,44,28,26,4,278,

■1. pandas

 pandasは、csvファイルなどを読み込んでからのデータ分析する前処理として、行列データの加工に便利です。例えば、指定した行や列を削除したり、指定条件の行や列データを抽出したり、行や列同士を計算したりもできます。また、他のファイルのデータを結合なども容易です。その理由は、行列の指定方法が、行番号や、行名、列名で操作できるためです。

 pandasの書式には二つあって、DataFrameとSeriesです。

下図は、DataFrameの場合の例です。Excelのように行列データ構造であって、必ず行名と列名を定義する必要があります。指定がない場合は数字で自動に割り当てられます。

f:id:HK29:20180917111449j:plain

一方、下図はSeriesの場合の例です。一見、2列に見えますが1列のデータ構造です。つまり、1次元構造であって列名はありません。但し、行名が必要です。指定がない場合は自動で数値が行番号としてあてがわれます。ちなみに、下図は上図のJulの列を抽出したものです。

f:id:HK29:20180917111521j:plain

■2. numpy

 numpyは、行列データ、もしくは1次元のデータの演算で使用します。ndarrayと呼ぶ書式で、print表示した場合、下図のように要素間がカンマ区切りではなく、隙間が空いて表記されます。

f:id:HK29:20180917113202j:plain

■3. list

 リストは、どのプログラミング言語にもあるように配列のことです。print表示した場合、下図のように要素間はカンマ区切りで表記されます。そのため、見た目には、numpyアレイとの識別はこのカンマの有無で出来ます。

f:id:HK29:20180917113227j:plain

 

以下は、雛形コードです。
次の1~4の流れに沿って、私が頻繁に使用するコードを備忘録として記載します。
1. 行列データファイルをpandasで読み込み
2. 行列データの前処理をする
3. numpyもしくはscikit-learnなどで計算
4. 最後にファイル保存

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np

def load_file():
    # pandasのdataframe書式でcsvファイルを読み込み 
    df = pd.read_csv(my_input, delimiter=',', index_col=0, header=0)
    print('df')
    print(df)
    print(type(df))

    ###################################################### 抽出関連
    # 列名を抽出。
    # 行名の場合はindex。to_numpy()でndarray化。更に、.tolist()でリスト化できる
    my_columns = df.columns #.to_numpy().tolist()
    print('my_columns')
    print(my_columns)

    # 欠損値がある列を削除。行の場合はaxis='index'で指定
    dfb = df.dropna(axis='columns')
    print('dfb')
    print(dfb)
    print(type(dfb))
    
    # 指定の1行を抽出: pandasのSeries書式になる
    # 名称で抽出する場合は「loc」。番号の場合は上記にあるように「iloc」
    dfc = df.loc[my_index, :]
    print('dfc')
    print(dfc)
    print(type(dfc))       

    # 指定の1列を抽出: pandasのSeries書式になる
    df3 = df.loc[:, my_col]
    print('df3')
    print(df3)
    print(type(df3))    

    # 指定行を排除。指定列の場合は、「列名, axis=1」
    dfe = df3.drop(my_index)
    print('dfe')
    print(dfe)
    print(type(dfe))

    # Dataframe書式において、行列名の指定から値を抽出: 
    val = df.loc[my_index, my_col]
    print('val of ' + my_index )
    print(val)

    # Series書式において、行名指定で値を抽出
    val3 = df3[my_index]
    print('val3 of ' + my_index )
    print(val3)

    ###################################################### 書式変換と演算
    # numpyのndarray書式
    nd = df3.to_numpy()
    print('mynp')
    print(nd)
    print(type(nd))      

    # list書式へ
    mylist = nd.tolist()
    print('mylist')
    print(mylist)
    print(type(mylist))
    
    # listをnumpyのndarray書式へ
    nd2 = np.array(mylist)
    print('nd2')
    print(nd2)
    print(type(nd2))
    
    # numpyで総和算出
    my_sum = np.sum(nd)
    print('my_sum')
    print(my_sum)

    # 全体に演算
    dfd = df3 * 0.1
    print('dfd')
    print(dfd)
    print(type(dfd))

    # 演算と四捨五入roundの場合, 指数表示の場合
    valA = val3 / my_sum
    print('valA = val3 / my_sum')
    print(valA)
    print(round(valA, 3))
    print("{0:.2e}".format(valA))

    ###################################################### pandas 結合
    # PandasのDataframe書式で行数や列数を調べる
    print('df.shape')
    print(df.shape)
    print('len(df)')
    print(len(df))
    print('len(df.columns)')
    print(len(df.columns))

    # 奇数行、偶数行を抜き出す方法    
    odd_list = [n for n in range(len(df)) if n % 2 == 1]
    print(odd_list) #[1, 3, 5, …]
    even_list = [n for n in range(len(df)) if n % 2 == 0]
    print(even_list) #[0, 2, 4, …]
    # 番号で抽出する場合は「iloc」
    df_o = df.iloc[odd_list]
    df_e = df.iloc[even_list]
    # 行方向(縦)の連結
    df_con = pd.concat([df_o, df_e])
    print('df_o')
    print(df_o)
    print('df_e')
    print(df_e)
    print('df_con')
    print(df_con)    
    
    # 列方向(横)の連結は、axis=1 共通ラベルのみを残す場合は、join='inner'
    df_con2 = pd.concat([df, df_o], axis=1, join='inner')
    print('df_con2')
    print(df_con2)

    ###################################################### ファイル保存
    # csvファイルに保存
    df_con.to_csv('df_con.csv', \
                     sep=',', index=False, encoding='utf-8', header=True)  


if __name__ == '__main__':
    input_file = './vegetables.csv'
    extract_column = 'Jul'
    extract_index = 'cucumber'

    load_file()

以上

<広告>