pandasで要素、行、列に関数を適用するmap, applymap, apply

Pythonの組み込み関数、自分で定義した関数を適用する場合は、以下のメソッドを使う。

  • Seriesの各要素に適用: map()
  • DataFrameの各要素に適用: applymap()
  • DataFrame, Seriesの各行・各列に適用: apply() 

    いずれのメソッドも、処理された新たなpandasオブジェクトを返し、元のオブジェクトは変更されない。dropna()やfillna()にあるような引数inplaceは存在しないので、元のオブジェクト自体を変更したい場合は、新たなオブジェクトを元のオブジェクトに代入して上書きする。
In [1]:
import pandas as pd
import numpy as np

df = pd.DataFrame({'a':[11, 21, 31],
                  'b':[12, 22, 32],
                  'c':[13, 23, 33],
                  'd':[14, 24, 34]})
print(df)
 
    a   b   c   d
0  11  12  13  14
1  21  22  23  24
2  31  32  33  34
 

Seriesの各要素に関数を適用: map()

Pythonの組み込み関数、無名関数(lambda)やdefで定義した関数をmap()の引数に渡す。

In [2]:
s = df['a']
print(s)

f_brackets = lambda x: '[{}]'.format(x)
print(s.map(f_brackets))
print(s.map(lambda x: '[{}]'.format(x)))

def f_str(x):
    return str(x).replace('1', 'One').replace('2', 'Two').replace('3', 'Three').replace('4', 'Four')

print(s.map(f_str))
 
0    11
1    21
2    31
Name: a, dtype: int64
0    [11]
1    [21]
2    [31]
Name: a, dtype: object
0    [11]
1    [21]
2    [31]
Name: a, dtype: object
0      OneOne
1      TwoOne
2    ThreeOne
Name: a, dtype: object
In [3]:
df['col'] = ['PCB,MO(4) FH-3050の2次処理面 TO PCB,MO(1) FH-3050-1..',
             'PCB,MO(4) FH-3050の2次処理面 TO PCB,MO(1) FH-3050-1..','PCB,MO(4) FH-3050の2次処理面 TO PCB,MO(1) FH-3050-1..']
s = df['col'].map(lambda x: str(x).rpartition(' TO ')[0])
print(s)

#print(s.map(lambda x: str(x).rpartition(' TO ')[0]))
 
0    PCB,MO(4) FH-3050の2次処理面
1    PCB,MO(4) FH-3050の2次処理面
2    PCB,MO(4) FH-3050の2次処理面
Name: col, dtype: object
In [4]:
s = 'PCB,MO(4) FH-3050の1次処理面 TO PCB,MO(4) FH-3050の2次処理面'
df['col'] = [s, s, s]
print(s.find('の'))
print(s[:s.find('の')])
#def f_str(s):
#    return str(s)[:s.find('PCB,MO(4) FH-3050', s.find('TO'))] + s[s.find('PCB,MO(4) FH-3050', s.find('TO')) + len('PCB,MO(4) FH-3050')+1:]

s = df['col'].map(lambda s: str(s)[:s.find(s[:s.find('の')], s.find('TO'))] 
                  + s[s.find(s[:s.find('の')], s.find('TO')) + len(s[:s.find('の')])+1:])
print(s)
#s[:s.find('PCB,MO(4) FH-3050', s.find('TO'))] + s[s.find('PCB,MO(4) FH-3050', s.find('TO')) + len('PCB,MO(4) FH-3050')+1:]
 
17
PCB,MO(4) FH-3050
0    PCB,MO(4) FH-3050の1次処理面 TO 2次処理面
1    PCB,MO(4) FH-3050の1次処理面 TO 2次処理面
2    PCB,MO(4) FH-3050の1次処理面 TO 2次処理面
Name: col, dtype: object
In [5]:
s = 'PCB,MO(4) FH-3050の1次処理面 TO PCB,MO(1) FH-3050-1の2次処理面'
df['col'] = [s, s, s]
s = df['col'].map(lambda s: str(s).replace('次処理',''))
print(s)
 
0    PCB,MO(4) FH-3050の1面 TO PCB,MO(1) FH-3050-1の2面
1    PCB,MO(4) FH-3050の1面 TO PCB,MO(1) FH-3050-1の2面
2    PCB,MO(4) FH-3050の1面 TO PCB,MO(1) FH-3050-1の2面
Name: col, dtype: object
 

DataFrameの各要素に関数を適用: applymap()

map()と同じく、Pythonの組み込み関数、無名関数(lambda)やdefで定義した関数をapplymap()の引数に渡す。

In [6]:
df = pd.DataFrame({'a':[11, 21, 31],
                  'b':[12, 22, 32],
                  'c':[13, 23, 33],
                  'd':[14, 24, 34]})

f_oddeven = lambda x: 'odd' if x % 2 == 1 else 'even'
print(df.applymap(f_oddeven))
 
     a     b    c     d
0  odd  even  odd  even
1  odd  even  odd  even
2  odd  even  odd  even
 

DataFrame, Seriesの各行・各列に適用: apply()

一次元配列に適用可能な関数をapply()の引数に渡す。デフォルトでは各列に対して適用され、引数axis=1とすると各行に対して適用される。

In [7]:
f_maxmin = lambda x: max(x) - min(x)
print(df.apply(f_maxmin))

print(df.apply(f_maxmin, axis=1))
 
a    20
b    20
c    20
d    20
dtype: int64
0    3
1    3
2    3
dtype: int64
 

DataFrameの特定の行・列の要素に適用

DataFrameの特定の行・列の要素にのみ関数を適用するメソッドはないので、

  • 行・列を選択し、Seriesとしてmap()で関数を適用
  • 元の行・列に代入して上書き 

    という処理を行う。
In [8]:
df['b'] = df['b'].map(f_str)
print(df)

df.iloc[2] = df.iloc[2].map(f_str)
print(df)
 
    a         b   c   d
0  11    OneTwo  13  14
1  21    TwoTwo  23  24
2  31  ThreeTwo  33  34
          a         b           c          d
0        11    OneTwo          13         14
1        21    TwoTwo          23         24
2  ThreeOne  ThreeTwo  ThreeThree  ThreeFour

空DataFrameの作成パターン

作成パターン

  • 空のデータフレームを作って、レコードを追加していくパターン
    • 新たに空のデータフレームを作成
    • 既存データフレームから空のデータフレームを作成
  • 行だけ確保した空のDataFrameを作って、後からカラムを加えていくパターン

空のデータフレームを作って、レコードを追加していくパターン

  • 新たに空のデータフレームを作成
In [1]:
import pandas as pd

cols = ['col1', 'col2']
df = pd.DataFrame(index=[], columns=cols)

record = pd.Series(['hoge', 'fuga'], index=df.columns)

for _ in range(5):
    df = df.append(record, ignore_index=True)

print(df)
 
   col1  col2
0  hoge  fuga
1  hoge  fuga
2  hoge  fuga
3  hoge  fuga
4  hoge  fuga
 
  • 既存データフレームから空のデータフレームを作成
In [2]:
df_blank = df.iloc[0:0]
print(df_blank)
df1 = df_blank.append(df)
print(df1)
 
Empty DataFrame
Columns: [col1, col2]
Index: []
   col1  col2
0  hoge  fuga
1  hoge  fuga
2  hoge  fuga
3  hoge  fuga
4  hoge  fuga
 

行だけ確保した空のDataFrameを作って、後からカラムを加えていくパターン

In [3]:
import pandas as pd
import numpy as np

# 元になるDataFrame
df = pd.DataFrame(np.random.random([100, 3]), columns=['foo', 'bar', 'baz'])
print(df.head())
print(len(df))
 
        foo       bar       baz
0  0.162949  0.610590  0.872259
1  0.732015  0.969791  0.022720
2  0.433584  0.245143  0.152153
3  0.857225  0.132263  0.565164
4  0.739305  0.010368  0.730865
100
 
  • 上記DataFrameをベースに、行だけ確保した空のDataFrameを作成
In [4]:
# カラムがないindexだけ設定されているDataFrameを作成
df_new = pd.DataFrame(index=df.index, columns=[])
print(df_new)
 
Empty DataFrame
Columns: []
Index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]

[100 rows x 0 columns]
 
  • カラムを1列ずつ計算して追加
In [5]:
# これにdfを整形したカラムを追加してみる
df_new['hoge'] = df.foo ** 2
print(df_new.head())
 
       hoge
0  0.026552
1  0.535846
2  0.187995
3  0.734834
4  0.546572
In [ ]:
 

pandas.DataFrameに列を追加(assign, contact)

import pandas as pd
import numpy as np
In [2]:
%%html
<style>
table {float:left}
td {text-align:left}
</style>
 
 

列名を指定して追加

In [3]:
df = pd.DataFrame({'A': ['A1', 'A2', 'A3'],
                   'B': ['B1', 'B2', 'B3'],
                   'C': ['C1', 'C2', 'C3']},
                  index=['ONE', 'TWO', 'THREE'])
print(df)
 
        A   B   C
ONE    A1  B1  C1
TWO    A2  B2  C2
THREE  A3  B3  C3
In [4]:
df['new column'] = [1, 2, 3]
print(df)
 
        A   B   C  new column
ONE    A1  B1  C1           1
TWO    A2  B2  C2           2
THREE  A3  B3  C3           3
 

DataFrame.assign

メソッド 引数 説明
DataFrame.assign (**kwargs) Assign new columns to a DataFrame, returning a new object (a copy) with the new columns added to the original ones.
 

pandas.DataFrameに新たな列を追加したり既存の列に新たな値を代入したりするためのメソッドとしてassign()が用意されている。

pandas.DataFrame.assign — pandas 0.22.0 documentation

 

assign()メソッドでは、キーワード引数列名=値で列名とその値を指定する。

既存の列名の場合は値が代入され、新規の列名の場合は新たな列が追加される。

注意:いずれも新たなオブジェクトが返され、元のオブジェクトは変更されない

In [5]:
df_new = df.assign(A=0)
print(df_new)
 
       A   B   C  new column
ONE    0  B1  C1           1
TWO    0  B2  C2           2
THREE  0  B3  C3           3
In [6]:
df_new = df.assign(D=0)
print(df_new)
 
        A   B   C  new column  D
ONE    A1  B1  C1           1  0
TWO    A2  B2  C2           2  0
THREE  A3  B3  C3           3  0
 

リストやpandas.Seriesなども値として指定可能。複数列を一括で追加・代入できる。(name属性は無視)

なお、assign()メソッドを使う場合は列名として数値を指定できないので注意。

In [7]:
s = pd.Series(['X2', 'X3', 'X4'], index=['TWO', 'THREE', 'FOUR'], name='X')
print(s)
df_new = df.assign(C='XXX',
                   D=0, E=[0, 1, 2],
                   F=s, G=s.values,
                   H=df['A'] + df['B'])
print(df_new)
 
TWO      X2
THREE    X3
FOUR     X4
Name: X, dtype: object
        A   B    C  new column  D  E    F   G     H
ONE    A1  B1  XXX           1  0  0  NaN  X2  A1B1
TWO    A2  B2  XXX           2  0  1   X2  X3  A2B2
THREE  A3  B3  XXX           3  0  2   X3  X4  A3B3
 

concat()関数でSeries, DataFrameを横に連結

pandas.concat()関数で引数axis=1として横方向に連結すると、pandas.Seriesのnameがpandas.DataFrameの列名となる。

pandas.concat()の第一引数に連結したいオブジェクトのリストやタプルを指定する。

In [8]:
df = pd.DataFrame({'A': ['A1', 'A2', 'A3'],
                   'B': ['B1', 'B2', 'B3'],
                   'C': ['C1', 'C2', 'C3']},
                  index=['ONE', 'TWO', 'THREE'])
print(df)
 
        A   B   C
ONE    A1  B1  C1
TWO    A2  B2  C2
THREE  A3  B3  C3
In [9]:
s = pd.Series(['X2', 'X3', 'X4'], index=['TWO', 'THREE', 'FOUR'], name='X')
print(s)
df_concat = pd.concat([df, s], axis=1, sort=True)
print(df_concat)
 
TWO      X2
THREE    X3
FOUR     X4
Name: X, dtype: object
         A    B    C    X
FOUR   NaN  NaN  NaN   X4
ONE     A1   B1   C1  NaN
THREE   A3   B3   C3   X3
TWO     A2   B2   C2   X2
 
  • 引数join='inner'として共通の行名の行のみを残すことも可能。
In [10]:
df_concat_in = pd.concat([df, s], axis=1, join='inner')
print(df_concat_in)
 
        A   B   C   X
TWO    A2  B2  C2  X2
THREE  A3  B3  C3  X3
 
  • 複数のpandas.Seriesを連結したり、pandas.DataFrameを連結したりすることもできる。
In [11]:
s1 = pd.Series(['X1', 'X2', 'X3'], index=df.index, name='X')
s2 = pd.Series(['Y1', 'Y2', 'Y3'], index=df.index, name='Y')

df_concat = pd.concat([df, s1, s2], axis=1)
print(df_concat)
 
        A   B   C   X   Y
ONE    A1  B1  C1  X1  Y1
TWO    A2  B2  C2  X2  Y2
THREE  A3  B3  C3  X3  Y3
In [12]:
df2 = pd.DataFrame({'df_col1': 0, 'df_col2': range(3)}, index=df.index)
print(df2)
df_concat2 = pd.concat([df, df2], axis=1)
print(df_concat2)
 
       df_col1  df_col2
ONE          0        0
TWO          0        1
THREE        0        2
        A   B   C  df_col1  df_col2
ONE    A1  B1  C1        0        0
TWO    A2  B2  C2        0        1
THREE  A3  B3  C3        0        2
In [ ]:
 

Python 標準ライブラリー

Python 標準ライブラリー

OSへのインタフェース

os モジュールは、オペレーティングシステムと対話するための多くの関数を提供しています

  • os.environ
  • os.getenv(key, default=None)
  • os.get_exec_path(env=None)

  • os.getlogin()

  • os.getpid()
  • os.getppid()
  • os.strerror(code)

  • os.chdir(path)

  • os.getcwd()

組み込み関数 dir() および help() は、 os のような大規模なモジュールで作業をするときに、対話的な操作上の助けになります.

In [ ]:
import os

print(os.getcwd())      # Return the current working directory
os.chdir('C:/Users/904PP4148/Documents')      # Change current working directory
print(os.getcwd()) 
os.system('mkdir today')   # Run the command mkdir in the system shell

dir(os)
help(os)
 

shutil --- 高水準のファイル操作

ファイルやディレクトリの日常的な管理作業のために、より簡単に使える高水準のインタフェースが shutil モジュールで提供されています.

  • shutil.copyfile(src, dst, *, follow_symlinks=True)
  • shutil.copy(src, dst, *, follow_symlinks=True)
  • shutil.copy2(src, dst, *, follow_symlinks=True) 
    copy2() はファイルの全てのメタデータを保持しようとすることを除けば copy() と等価です。
  • shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False) 
    src をルートにしたディレクトリツリー全体をコピーして、コピー先ディレクトリを返します。
  • shutil.rmtree(path, ignore_errors=False, onerror=None) 
    ディレクトリツリー全体を削除します。
  • shutil.move(src, dst, copy_function=copy2) 
    ファイルまたはディレクトリ (src) を再帰的に別の場所 (dst) に移動して、移動先を返します。
  • shutil.disk_usage(path) 
    指定されたパスについて、ディスクの利用状況を、名前付きタプル (named tuple) で返します。
In [ ]:
import shutil

shutil.copyfile('fileA', 'fileB')
shutil.move('/build/executables', 'installdir')
 

ファイルのワイルドカード表記

glob モジュールでは、 
ディレクトリのワイルドカード検索からファイルのリストを生成するための関数を提供しています.

In [ ]:
import glob

glob.glob('*.py')
 

コマンドライン引数

In [ ]:
import sys
print(sys.argv)
 

エラー出力のリダイレクトとプログラムの終了

  • sys モジュールには、 stdin, stdout, stderr を表す属性も存在します。 
    stderr は、警告やエラーメッセージを出力して、 
    stdout がリダイレクトされた場合でも読めるようにするために便利です。

  • sys.exit() は、スクリプトを終了させるもっとも直接的な方法です。

In [ ]:
sys.stderr.write('Warning, log file not found starting a new one\n')
 

文字列のパターンマッチング

re モジュールでは、より高度な文字列処理のための正規表現を提供しています。 
正規表現は複雑な一致検索や操作に対して簡潔で最適化された解決策を提供します。

In [31]:
import re
rst = re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
print(rst)
rst = re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
print(rst)
 
['foot', 'fell', 'fastest']
cat in the hat
 

最小限の機能だけが必要なら、読みやすくデバッグしやすい文字列メソッドの方がお勧めです。

In [32]:
rst = 'tea for too'.replace('too', 'two')
print(rst)
 
tea for two
 

数学

  • math モジュールは、浮動小数点演算のための C 言語ライブラリ関数にアクセスする手段を提供しています
In [33]:
import math

print(math.cos(math.pi / 4))
print(math.log(1024, 2))
 
0.7071067811865476
10.0
 
  • random モジュールは、乱数に基づいた要素選択のためのツールを提供しています
In [38]:
import random
print(random.choice(['apple', 'pear', 'banana']))
print(random.sample(range(100), 10))    # sampling without replacement
print(random.random())    # random float
print(random.randrange(6))    # random integer chosen from range(6)
 
pear
[32, 11, 21, 86, 92, 1, 55, 65, 18, 84]
0.8716232430159375
2
 
  • statistics モジュールは数値データの基礎的な統計的特性(平均、中央値、分散等)を計算します
In [39]:
import statistics
data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
print(statistics.mean(data))
print(statistics.median(data))
print(statistics.variance(data))
 
1.6071428571428572
1.25
1.3720238095238095
 
  • SciPy プロジェクト https://scipy.org は数値処理のための多くのモジュールを提供しています。
 

インターネットへのアクセス

インターネットにアクセスしたりインターネットプロトコルを処理したりするための多くのモジュールがあります。 
最も単純な2つのモジュールは、 
URL からデータを取得するための urllib.request と、 
メールを送るための smtplib です。

In [43]:
from urllib.request import urlopen
with urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl') as response:
    for line in response:
        line = line.decode('utf-8')  # Decoding the binary data to text.
        if 'EST' in line or 'EDT' in line:  # look for Eastern Time
            print(line)
 
<BR>Jun. 25, 10:42:47 PM EDT		Eastern Time

 
ProxyHandler --- urllibプロキシ設定
In [1]:
import urllib

proxy = urllib.request.ProxyHandler({'http': '127.0.0.1'})
opener = urllib.request.build_opener(proxy)
urllib.request.install_opener(opener)
 

localhost でメールサーバーが動いている必要がある

In [ ]:
import smtplib
server = smtplib.SMTP('localhost')
server.sendmail('soothsayer@example.org', 'jcaesar@example.org',
    """To: jcaesar@example.org
       From: soothsayer@example.org

       Beware the Ides of March.
    """)
server.quit()
 

日付と時刻

datetime モジュールは、日付や時刻を操作するためのクラスを、単純な方法と複雑な方法の両方で提供しています

In [49]:
from datetime import date
now = date.today()
print(now)
print(now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B."))

birthday = date(1964, 7, 31)
age = now - birthday
print(age.days)
 
2018-06-26
06-26-18. 26 Jun 2018 is a Tuesday on the 26 day of June.
19688
 

データ圧縮

一般的なデータアーカイブと圧縮形式は、以下のようなモジュールによって直接的にサポートされます:

In [53]:
import zlib
s = b'witch which has which witches wrist watch'
print(len(s))
t = zlib.compress(s)
print(t)
print(len(t))
print(zlib.decompress(t))
print(zlib.crc32(s))
 
41
b'x\x9c+\xcf,I\xceP(\xcf\xc8\x04\x92\x19\x89\xc5PV9H4\x15\xc8+\xca,.Q(O\x04\xf2\x00D?\x0f\x89'
37
b'witch which has which witches wrist watch'
226805979
 

パフォーマンスの計測

timeit では小さい粒度を提供しているのに対し、 
profile や pstats モジュールではより大きなコードブロックにおいて 
律速となる部分を判定するためのツールを提供しています。

In [54]:
from timeit import Timer
t1 = Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
print(t1)
t2 = Timer('a,b = b,a', 'a=1; b=2').timeit()
print(t2)
 
0.13873595824864515
0.0672354037715018
 

品質管理

  • doctest モジュールでは、モジュールを検索してプログラムの docstring 
    に埋め込まれたテストの評価を行うためのツールを提供しています。
  • unittest モジュールは、より網羅的なテストセットを別のファイルで管理することができます
In [56]:
def average(values):
    """Computes the arithmetic mean of a list of numbers.

    >>> print(average([20, 30, 70]))
    40.0
    """
    return sum(values) / len(values)

import doctest
doctest.testmod()   # automatically validate the embedded tests
Out[56]:
TestResults(failed=0, attempted=1)
In [ ]:
import unittest

class TestStatisticalFunctions(unittest.TestCase):

    def test_average(self):
        self.assertEqual(average([20, 30, 70]), 40.0)
        self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
        with self.assertRaises(ZeroDivisionError):
            average([])
        with self.assertRaises(TypeError):
            average(20, 30, 70)

unittest.main()  # Calling from the command line invokes all tests

pandasデータのイテレーション(forループ処理)

pandasデータのイテレーション

pandas ではデータを 列 や 表形式のデータ構造として扱うが、 
これらのデータから列ごと・行ごと(一列ずつ・一行ずつ)に値を取得 
(イテレーション) して何か操作をしたい ことがよくある。

Series のイテレーション

eries は以下 2つのイテレーション用メソッドを持つ。各メソッドの挙動は以下のようになる。

In [1]:
import pandas as pd
s = pd.Series([1, 2, 3], index=['a', 'b', 'c'])

# Series の値 ( values ) のみをイテレーション
for v in s:
    print(v)
    
# index と values からなる tuple をイテレーション
for i, v in s.iteritems():
    print(str(i) + ' ' + str(v))
 
1
2
3
a 1
b 2
c 3
 

DataFrame のイテレーション

DataFrame は以下 4つのイテレーション用メソッドを持つ。同様に挙動を示す。

In [2]:
import pandas as pd

df = pd.read_csv('data/sample_pandas_normal.csv', index_col=0).head(2)
print(df)

# DataFrame の列名 ( columns ) のみをイテレーション
for column_name in df:
    print(column_name, type(column_name))
 
       age state  point
name                   
Alice   24    NY     64
Bob     42    CA     92
age <class 'str'>
state <class 'str'>
point <class 'str'>
In [3]:
#  DataFrame の列名と 列の値 ( Series ) からなる tuple をイテレーション
for column_name, item in df.iteritems():
    print(column_name, type(column_name))
    print(item, type(item))

    print(item['Alice'], item[0], item.Alice)
    print('======\n')
    
 
age <class 'str'>
name
Alice    24
Bob      42
Name: age, dtype: int64 <class 'pandas.core.series.Series'>
24 24 24
======

state <class 'str'>
name
Alice    NY
Bob      CA
Name: state, dtype: object <class 'pandas.core.series.Series'>
NY NY NY
======

point <class 'str'>
name
Alice    64
Bob      92
Name: point, dtype: int64 <class 'pandas.core.series.Series'>
64 64 64
======

In [4]:
# DataFrame の行名と 行の値 ( Series ) からなる tuple をイテレーション
for index, row in df.iterrows():
    print(index, type(index))
    print(row, type(row))

    print(row['point'], row[2], row.point)
    print('======\n')
 
Alice <class 'str'>
age      24
state    NY
point    64
Name: Alice, dtype: object <class 'pandas.core.series.Series'>
64 64 64
======

Bob <class 'str'>
age      42
state    CA
point    92
Name: Bob, dtype: object <class 'pandas.core.series.Series'>
92 92 92
======

In [5]:
# DataFrame の**行名と 行の値からなるタプル ** をイテレーション
# デフォルトではPandasという名前のnamedtupleを返す。
for row in df.itertuples():
    print(row, type(row))

    print(row[3], row.point)
    print('======')
    
 
Pandas(Index='Alice', age=24, state='NY', point=64) <class 'pandas.core.frame.Pandas'>
64 64
======
Pandas(Index='Bob', age=42, state='CA', point=92) <class 'pandas.core.frame.Pandas'>
92 92
======
In [6]:
# 引数nameをNoneとするとノーマルのタプルを返す。
for row in df.itertuples(name=None):
    print(row, type(row))

    print(row[3])
    print('======\n')
 
('Alice', 24, 'NY', 64) <class 'tuple'>
64
======

('Bob', 42, 'CA', 92) <class 'tuple'>
92
======

 

GroupBy

GroupBy は以下のイテレーション用メソッドを持つ。

  • iter: GroupBy のグループ名と グループ ( DataFrame もしくは Series ) からなる tuple をイテレーション
In [7]:
df = pd.read_csv('data/sample_pandas_normal.csv', index_col=0)
print(df)

grouped = df.groupby('state')
for name, group in grouped:
    print(name)
    print(group)    
    print('======')
 
         age state  point
name                     
Alice     24    NY     64
Bob       42    CA     92
Charlie   18    CA     70
Dave      68    TX     70
Ellen     24    CA     88
Frank     30    NY     57
CA
         age state  point
name                     
Bob       42    CA     92
Charlie   18    CA     70
Ellen     24    CA     88
======
NY
       age state  point
name                   
Alice   24    NY     64
Frank   30    NY     57
======
TX
      age state  point
name                  
Dave   68    TX     70
======
 

ループ処理で値を更新する

1行ずつ値を取り出すiterrows()メソッドはビューではなくコピーを返すので、 
pandas.Seriesを変更しても元データは更新されない。

In [8]:
for index, row in df.iterrows():
    row.point /= 2
print(df)
 
         age state  point
name                     
Alice     24    NY     64
Bob       42    CA     92
Charlie   18    CA     70
Dave      68    TX     70
Ellen     24    CA     88
Frank     30    NY     57
 
  • at で元のDataFrameからデータを選択して処理する必要がある。
In [9]:
for index, row in df.iterrows():
    df.at[index, 'point'] /= 2

print(df)
 
         age state  point
name                     
Alice     24    NY     32
Bob       42    CA     46
Charlie   18    CA     35
Dave      68    TX     35
Ellen     24    CA     44
Frank     30    NY     28