pandasでDataFrameから行をSeriesとして抽出した場合、暗黙の型変換が実行されるので注意

環境

python, pandas, jupyter のバージョン

> python --version
# Python 3.7.4

import pandas as pd
pd.__version__
# '0.25.2'

> jupyter notebook --version
# 6.0.1

発生事象

データ分析中にエラーに遭遇した。簡単なデータを使って再現すると、以下のようになる。
以下、jupyter notebook上で実行した。出力された結果は# ---の後に記載している。

df = pd.DataFrame({
    'float_col'  : [1.1, 2.2, 3.3, 4.4, 5.5, 6.6],
    'int_col'    : [0, 2, 4, 1, 3, 5]    
})
df

---

       float_col  int_col
    0        1.1        0
    1        2.2        2
    2        3.3        4
    3        4.4        1
    4        5.5        3
    5        6.6        5
arr = list(range(10, 61, 10))
arr

---

    [10, 20, 30, 40, 50, 60]
idx = df.loc[2]["int_col"]
arr[idx]
---

    ---------------------------------------------------------------------------

    TypeError                                 Traceback (most recent call last)

    <ipython-input-6-90a797f8b25e> in <module>
          1 idx = df.loc[2]["int_col"]
    ----> 2 arr[idx]
    

    TypeError: list indices must be integers or slices, not numpy.float64

idxには4が入っていると思っていたが、なぜか配列の添え字に指定するとエラーになった。 エラーメッセージはTypeError: list indices must be integers or slices, not numpy.float64である。すなわち、 listのインデックスに指定できるのは整数かスライスだけで、numpy.float64 はダメだ、という意味だ。 え?整数のはずなのに、何でnumpy.float64になったの?

idx

---

4.0
type(idx)

---

    numpy.float64

idxはnumpy.float64型の浮動小数点数4.0だったので、配列の添え字に使うとエラーになったというわけだ。では、なぜfloatになっていたのか?

仕組み、理由

実は、さっきの例では、少し変なlocの使い方をしていた。
df.loc[行名, 列名]の形で指定要素を取り出せるのに、さっきはdf.loc[行名][列名]と2回添え字を使っていた。
確かに、これでも結果として指定される要素は同じだ。しかしこの違いが、さっきのエラーを引き起こしたのだ。

df.loc[2]の時点で、単独の行をいったん選択・抽出している。単独の行とはすなわちSeriesであり、それは単一の型を持たねばならない。
ではその型は何か?
floatとintを両方格納できる型、すなわちfloatである。そしてintの4はこのときfloatの4.0へと自動的に型変換(キャスト)されたのだ。

df.dtypes

---

    float_col    float64
    int_col        int64
    dtype: object
df.loc[2]

---

    float_col    3.3
    int_col      4.0
    Name: 2, dtype: float64

したがって、整数値を整数のまま取り出しエラーを回避するには、df.loc[行名, 列名]の形で要素を指定すればよい。こうすれば途中でSeriesを経由しないので、型変換も実行されず、整数の4は整数のままである。

idx2 = df.loc[2, "int_col"]
arr[idx2]

---

    50

同様の事象

仕組みが分かれば簡単な話である。この事象が発生する仕組みを改めて書くと、以下のようになるだろう。

  • floatの列とint型の列が混在したDataFrameから
  • 1行をSeriesとして抜き出すと
  • int型の値が暗黙のうちに型変換(キャスト)されて、float型になる

したがって、locに限らず1行を選択・抽出すると同様の事象が発生する。
思いつくままに並べると、次のようになるだろう。

  • loc, iloc
  • iterrows
  • 転置

locが行の名称を指定して行を選択するのに対して、ilocは行の位置(何行目か)を指定して行を選択する。ilocの場合もほとんど同様なので、説明は割愛する。

iterrows

iterrowsはDataFrameの各行を順番に抜き出す。listに対してforを使うのと同じような働きをする。
予想通り、int_colの値はすべてfloatになっていた。

for _, row in df.iterrows():
    print(row["int_col"])

---

    0.0
    2.0
    4.0
    1.0
    3.0
    5.0

なお、iterrowsのほうは公式ドキュメントに注意事項として書いてある。

pandas.DataFrame.iterrows — pandas 0.25.3 documentation

Because iterrows returns a Series for each row, it does not preserve dtypes across the rows (dtypes are preserved across columns for DataFrames).
拙訳:iterrowsは各行についてSeriesを返すので、行の中のdtypeは保存されない。(dtypesはDataFrameの列の中で保存されている)*1

転置

DataFrameの転置は、1行を選択・抽出するわけではない。 しかし、行と列を入れ替えるので、既存のDataFrameの各行をSeriesとして扱うことになり、結果としてlocやiterrowsなどと同じ状況が発生する。

df_t = df.transpose()
df_t

# ---

             0    1    2    3    4    5
float_col  1.1  2.2  3.3  4.4  5.5  6.6
int_col    0.0  2.0  4.0  1.0  3.0  5.0

転置後のint_colが行になるが、これらの数値が浮動小数点数で表記されていることに注意。 なお、転置のほうは公式ドキュメントに注意事項として書いてある。

pandas.DataFrame.transpose — pandas 0.25.3 documentation

Notes Transposing a DataFrame with mixed dtypes will result in a homogeneous DataFrame with the object dtype. In such a case, a copy of the data is always made.
拙訳: 複数のdtypeからなるDataFrameを転置すると、objectのdtypeを持つ同質的なDataFrameが出来上がる。このような場合、常にデータのコピーができる。

関連

strが入っているとobjectになるから結果的に大丈夫ぽい。あとで。

型に関する公式ドキュメントでちょうど良いページが見つからなくて、困っている。
素直に「pandas dtype」で検索すると出るページはこれ。
pandas.DataFrame.dtypes — pandas 0.25.3 documentation しかし、このページの説明はとても簡単なことしか書いていない。このページから行ける下記のページが、dtypeに関する公式情報かな?
Essential basic functionality — pandas 0.25.3 documentation

以下は、この記事で扱ってきた内容と似ているが少し違う例である。DataFrameを結合したらintの列にNaNが混じり、floatに自動的に型変換されたというものである。
Python: pandas で DataFrame を連結したら dtype が int から float になって驚いた話 - CUBE SUGAR CONTAINER

*1:acrossの訳し方むずい……

Effective Python 第2版(原著)が出るみたいだよ

Effective Pythonの第2版(英語)が発行されるという話を、しばらく前から見かけていた。 最近になって、著者のBrett Slatkin氏が、とうとう発行されるというツイートをしていた。

日本時間で10月23日の0:59と、つい最近のことだ。

Effective Pythonの公式サイト: effectivepython.com

公式GitHubも第2版に合わせて改訂されたようだ。
GitHub - bslatkin/effectivepython: Effective Python: Second Edition — Source Code and Errata for the Book

時系列を整理しておこう。
第1版の原著:2015年3月発行(amazon.comの情報より)
第1版の日本語版:Effective PythonPythonプログラムを改良する59項目 amazon.co.jpオライリー 2016年1月発行
第2版の原著:amazon.com上での発売予定日は(何度か延期されて、現在は)2019年12月2日となっている。著者ツイートによれば、11月半ばには発送されるとのこと。

本の内容

第1版では「59項目」となっていたが、第2版では約30項目増えて「90項目」となった。著者のコメントによれば、追加ではない既存の項目についても、加筆修正した部分が多くあるようだ。
本の説明の中には「Pythonic」という言葉が散見される。どうも定義がはっきりしないようだが、Pythonらしい書き方とはどういうものか、について書いてあるようだ。俺は基本的な文法は習得したが、Pythonらしく上手く書けている自信がないので、この本はうってつけと言える。

第2版は日本語訳されるのか?

少し前にEffective Python(第1版、日本語)を買おうとした。しかしamazon.co.jp上のレビューで「翻訳が分かりにくい」というコメントを見かけて、本屋に行って見てみたら確かに看過できないほど硬い表現があったので、買うのをやめた。
第2版は日本語訳されるのだろうか。もし日本語に翻訳されるのであれば、質の悪さを咎められることのないような翻訳になってくれればよいと祈るばかりである。あとは翻訳を待つのをやめて、原著で読むのに挑戦するというのも一つの手かもしれない。


2020年6月24日 追記

Effective Python 第2版 日本語版が出るよ

O'Reilly Village/オラの村 - 7月新刊情報『Effective Python 第2版』
オライリーより2020年7月16日に発売予定。
ページ数は第1版の256ページから、456ページ(予定)に大幅増加した。すごいな。
翻訳者は第1版と同じく、黒川利明氏である。


翻訳の改善提案を少しずつ書いていこうと思います。

linus-mk.hatenablog.com

[pandas]groupbyの最初・最後の行を求めるfirst・last関数の話、headやnthとの違い

pandasで、ある特定の列の値に応じてグループ化(集計・集約)し、特定の列の値ごとに最初の行(もしくは最後の行)を求めたいときの話。

ある特定の列の値に応じてグループ化するにはgroupby関数を使う。 pandasのgroupby関数の返り値はGroupByオブジェクトというやつになる。(正確にはDataFrameGroupByまたはSeriesGroupByオブジェクト)GroupByオブジェクトに対して、やりたい操作に対応する関数を適用すれば結果が求まる。平均のmeanや合計のsum、最大値のmaxなどが有名だろう。

で、「グループごとの最初のレコードが欲しいんだけど、そういう関数はあるのだろうか」と思い、 "pandas groupby first"で検索したら、普通に出てきた。firstという関数があるので、それを使えばよい。

first関数の説明ページはこちら。
pandas.core.groupby.GroupBy.first — pandas 0.25.1 documentation

pandas.core.groupby.GroupBy.first
Compute first of group values.

これだけ。説明はいたって単純だ。

また、StackOverflowの質問を色々見ていたら、firstの他にnth、headを使っても同様のことができると書いてあったので、合わせて実験してみよう。
特に、NaNを含むときには挙動が複雑になり、思わぬ落とし穴にはまる可能性もあるので、詳述している。

基本的な例:グループごとに最初の行を選択する(first、nth、head)

以下、出力された結果は# ---の後に記載している。

import pandas as pd
<200b>
df = pd.DataFrame({
    'name'    : ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Fred', 'George', 'Helen', 'Ian', 'John'],
    'class'   : ['A', 'A', 'B', 'B', 'A', 'C', 'A', 'B', 'C', 'C'],
    'English' : list(range(0, 100, 10)),
    'Math'    : list(range(100, 0, -10))
})
df

# ---

      name class  English  Math
0    Alice     A        0   100
1      Bob     A       10    90
2  Charlie     B       20    80
3    David     B       30    70
4      Eve     A       40    60
5     Fred     C       50    50
6   George     A       60    40
7    Helen     B       70    30
8      Ian     C       80    20
9     John     C       90    10
df.groupby("class")

# ---

<pandas.core.groupby.generic.DataFrameGroupBy object at 0x03DB2950>

groupbyの結果はDataFrameGroupBy オブジェクトであった。これに対して各関数を適用し、結果を見てみよう。

df.groupby("class").first()

# ---

          name  English  Math
class                        
A        Alice        0   100
B      Charlie       20    80
C         Fred       50    50

もとのデータと見比べて欲しい。各Classの最初のデータだけが抽出されたことが分かる。

df.groupby("class").nth(0)

# ---

          name  English  Math
class                        
A        Alice        0   100
B      Charlie       20    80
C         Fred       50    50

n番目の行を表示するための関数なので、n番目→n-th→nth関数という名前になったようだ。
最初の行を表示したいので、引数に0を指定する。結果はfirstの時と全く同じだ。

df.groupby("class").head(1)

# ---

      name class  English  Math
0    Alice     A        0   100
2  Charlie     B       20    80
5     Fred     C       50    50

head関数は「グループごとに最初のn行を表示する」メソッドである。今回は最初の1行だけが欲しいので引数に1を入れている。
first、nthの結果では、groupbyに用いていたclass列が行名に移動している。それに対して、headの結果ではclass列は元のままで、元のindexが行名に使われている。

基本的な例:グループごとに最後の行を選択する(last、nth、tail)

正反対の操作、つまりグループごとに最後の行を選択する操作の例である。 先ほどとほぼ同じ話なので、簡潔に述べる。

  • firstの反対がlast
  • nthは関数名は変わらない。最後の要素を指定するために引数に-1を入れる
  • headの反対がtail
df.groupby("class").last()

# ---

         name  English  Math
class                       
A      George       60    40
B       Helen       70    30
C        John       90    10
df.groupby("class").nth(-1)

# ---

         name  English  Math
class                       
A      George       60    40
B       Helen       70    30
C        John       90    10
df.groupby("class").tail(1)

# ---

     name class  English  Math
6  George     A       60    40
7   Helen     B       70    30
9    John     C       90    10

NaNを含むときの挙動

よく似た挙動をするこれらの関数だが、データにNaNが入っていた場合がなかなか厄介なようだ。
最初の行の方だけしか確認していないが……最後の行についても同様だろう。

まずNaNが混じったデータを作ります。

df = pd.DataFrame({
    'name'    : ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Fred', 'George', 'Helen', 'Ian', 'John'],
    'class'   : ['A', 'A', 'B', 'B', 'A', 'C', 'A', 'B', 'C', 'C'],
    'English' : list(range(0, 100, 10)),
    'Math'    : list(range(100, 0, -10))    
})
import numpy as np
df.loc[0, "name"] = np.nan
df.loc[0, "English"] = np.nan
df.loc[0, "Math"] = np.nan
df.loc[1, "Math"] = np.nan
df.loc[5, "English"] = np.nan
df

# ---

      name class  English  Math
0      NaN     A      NaN   NaN
1      Bob     A     10.0   NaN
2  Charlie     B     20.0  80.0
3    David     B     30.0  70.0
4      Eve     A     40.0  60.0
5     Fred     C      NaN  50.0
6   George     A     60.0  40.0
7    Helen     B     70.0  30.0
8      Ian     C     80.0  20.0
9     John     C     90.0  10.0

単純なほうから述べる。

まずheadは、単純に先頭からN行を抜き出す動作であり、NaNであろうがなかろうが関係ない。 pandas.core.groupby.GroupBy.head — pandas 0.25.2 documentation

df.groupby("class").head(1)

# ---

      name class  English  Math
0      NaN     A      NaN   NaN
2  Charlie     B     20.0  80.0
5     Fred     C      NaN  50.0

nth

次にnthについて。
この関数にはdropnaパラメータがある。dropnaにはNone、'any'、'all'を指定できる。デフォルトはNoneだ。 pandas.core.groupby.GroupBy.nth — pandas 0.25.2 documentation

dropna=NoneはNaNかどうかを気にせずに数えて、n番目の行を抜き出す。

df.groupby("class").nth(0)

# ---

          name  English  Math
class                        
A          NaN      NaN   NaN
B      Charlie     20.0  80.0
C         Fred      NaN  50.0

dropna='any'は、どれか1つの列でもNaNがあったらその行はノーカウントとする。
下の例だとclass AとCの結果が変わっている。

df.groupby("class").nth(0, dropna="any")

# ---

          name  English  Math
class                        
A          Eve     40.0  60.0
B      Charlie     20.0  80.0
C          Ian     80.0  20.0

dropna='all'は、全ての列がNaNであったらその行はノーカウントとする。

df.groupby("class").nth(0, dropna="all")

# ---

          name  English  Math
class                        
A          NaN      NaN   NaN
B      Charlie     20.0  80.0
C         Fred      NaN  50.0

あれれ。全ての列がNaNの行が選択されている。公式ドキュメントは

If dropna, will take the nth non-null row, dropna is either ‘all’ or ‘any’; this is equivalent to calling dropna(how=dropna) before the groupby.

なので、groupnbyに使った列(class)もNaNの場合に限ってノーカウント、ということか?よく分からない。

first

最後にfirstだ。この関数はかなり奇妙な動作をしていて、落とし穴になるので要注意だ。 「列ごとに、1番目から見ていって、最初にNaNでない値を表示する」という動きになる。列ごとに全く独立であることに注意。
といってもわかりづらいので、具体例を出そう。

df.groupby("class").first()

# ---

          name  English  Math
class                        
A          Bob     10.0  60.0
B      Charlie     20.0  80.0
C         Fred     80.0  50.0

Class Cの場合、name列とMath列は1行目(5、Fred)にNaNでないデータがあるのでそれを使う。
一方、Englishの列は1行目がNaNなので、その次のデータ(8、Ian)を使う。
結果として、別々の行から継ぎはぎしたデータが返ってくるのだ!
Class Aでも同様だ。

pandas開発のGitHubの中で、関連するissueは以下。バグなのか仕様なのか分からないが、最初の報告は2014年と、ずいぶん昔からこの挙動のようだ。
BUG: groupby.first/last with nans · Issue #8427 · pandas-dev/pandas · GitHub

このStackOverflowの質問経由で、firstがNaNの時の挙動を知った。 python - pandas: how do I select first row in each GROUP BY group? - Stack Overflow


groupbyをした後に使える関数一覧は、公式ドキュメントのここに書いてある。
GroupBy — pandas 0.25.1 documentation

その中でもよく使う関数は、公式ドキュメントのGroupByのユーザーズガイドに書いてある。
Group By: split-apply-combine — pandas 0.25.2 documentation

firstに関連する質問。 python - Pandas dataframe get first row of each group - Stack Overflow

GitHubの中で、上述したfirstの挙動に関するissue一覧。 BUG: groupby.first/last with nans · Issue #8427 · pandas-dev/pandas · GitHubこれは先ほども記載したもの
groupby().first() skips NaN values · Issue #6732 · pandas-dev/pandas · GitHub

まだ調べればいろいろありそうだけど、書き続けて疲れたのでこの辺で。
それでは。

「やったもん負けの」「出る杭は打たれる」組織内では役割外行動が抑圧される。

f:id:soratokimitonoaidani:20191013134516p:plain

前の会社を退職したときに、何度か送別会を開いてもらった。その中で、「あなたが書いた言葉は、会社に爪痕を残したのだ」と言われたことがある。 その俺の言葉とは、「やったもん負け」である。
俺が最初に言い出したように思われていたが、そうではない。 元々は、社内掲示板で直前に誰かが「この会社が、やったもん勝ちの文化になるように」していきたいと書いていた。 俺がそれを裏返して「現状そうなってないじゃん。今の社内はやったもん負けの空気になっちゃってるじゃん」と書いた。(細かい文面は忘れたが)別に俺が発明した語句ではない。俺はすぐ前に書いた人の逆を書き込んだだけだ。
ともあれ、俺が投稿した文章が偉い人の目に留まったようである。 『やったもん負け』というフレーズは少し形を変えて、社内のどこかの研修資料に残っているらしい。 そういう意味で、俺の書き連ねた言葉は会社に爪痕を残したんだ、という話であった。


それから日は流れて、前職での最終出社日がついにやってきた。 同期に退職の挨拶をして回る中で、同期の一人と会って少し話をした。 彼はよく喋り、声の大きい、外向的な性格で、俺とはまるで正反対だが、たまに声をかけられて話すこともあった。 技術がすごいというタイプではないが、なかなかの慧眼というか、本質を見抜くのが上手い人だ。
前後の脈絡はすっかり忘れてしまったが、その彼が 「だってさ、この会社で大事なのは、いかに波風立てずに大人しくやっていくかじゃん?」と唐突に言いだした。 俺は思わず天を仰いでしまった。 彼の目にはこの会社がそう映っているのか、と。


「やったもん負け」「波風立てずに」と、組織の文化について同じような言葉を続けざまに聞いた。 似たような表現で、出る杭は打たれる、という言葉もある。

会社組織というものはどうなっているのだろうか、 この組織はどうやって出来上がっているのだろうか、と考えて、 次第に人的資源管理や組織論の本を読むようになった。

組織行動 (鈴木竜太・服部泰弘 著、有斐閣ストゥディア)」を読んだ時に、 役割外行動の話を見つけた。 役割外行動というのは聞き慣れない言葉だが、「職務の範疇外の自発的・革新的な行動をすること」という意味である。 1つ前のエントリでまとめたので、参照されたい。

linus-mk.hatenablog.com

役割外行動の話を読んだ俺は、前職でどんな役割外行動をしただろうと考えてみた。
会社の業務以外に、俺がやっている技術関連の行動を思いつくままに挙げてみると、次のようになる。

  • 勉強会に行く
  • ごくまれに勉強会で発表をする
  • 競技プログラミングをする
  • このブログを書く
  • 技術書を読む
  • ごくまれに個人的にコードを書いてGitHubにアップする

では、これらは「組織の役割外の行動」なのだろうか。
いや、違う。これらの行動は、組織に関係ない話である。
勉強会で得た内容は、少なくとも前職の業務に役立ってはいないし、会社にその知見を共有したわけでもない。 競技プログラミングから得たアルゴリズムの能力は、業務を遂行する上で役立ったかもしれないが、組織への貢献を念頭において競技プログラミングに励んだわけではない。

俺はなぜ、これらの行動をしているのだろうか。
短期的な視点で言えば、技術を習得して(前職から)転職するため、というのが一つの目的だ。
だが、より長期的な視点で言えば、自分がエンジニアとして食いっぱぐれないようにするためだ*1。 エンジニアとしての能力を向上させて、もし会社が傾いたとしても他の会社で雇ってもらえるようにするためだ。 人事管理(人的資源管理)の用語で言うと、「エンプロイアビリティの向上」と呼ばれる。 エンプロイアビリティのとは、以下のような意味だ。

エンプロイアビリティとは、一つの組織内だけで通用する職業能力ではなく、企業の枠を超えて広く雇用市場で通用する個人の職業能力や専門能力のこと。
「エンプロイメンタビリティ」とは? - 『日本の人事部』

組織に対して愛着や貢献心が強いわけでもないので、自分が気分よく働ければそれで良し、という主義である。
エンジニアとして学習し能力を向上させることの重要性は、繰り返し語られている。 例えば、「SOFT SKILLS」にはこのように書いてある。

プロが高い基準を満たすために行っているのは、継続的な自己研鑽である。プロになりたければ、いつも全力を挙げて自分のスキルを向上させ、自分の技術についてより多くのことを学ばなければならない。スキルを広げるための自己訓練プランを立て、仕事の質を高めるために役立つ新しい情報を学ぶようにしよう。十分いいという線で満足してはならない。常にもっといい自分を求め続けよう。
SOFT SKILLS p.56

上記の行動は組織と無関係なので、組織の利益になる行動ではない。したがって、組織の中の役割外行動ではない。
では、もう一度考えてみよう。私が前職において実行した、役割外の行動は何だったのか?

  • チームに対してRedmineを導入する
  • フロアの冷蔵庫や棚の中の、賞味期限がとっくに切れた飲み物と食べ物を捨てる
  • 会議スペースのホワイトボード用マーカーが出なくなったまま放置されていたのを捨て、新しいものを持ってくる
  • フロアで壊れたまま放置されていた椅子の修理を依頼する

あれ、さっきと違う。技術的な話がどっかにいってしまった。(RedMineは技術だけど。)
色々と技術的な研鑽をしていた俺が、それを前職に持ち込まなかった理由は何なんだろうか?

思うに、技術領域の目的外行動を会社に対して起こさなかった理由の一つが「出る杭が打たれる」組織文化ではないか。

役割どおり、上司からの命令に従って作業をする、というのは役割外行動ではない。 上司から言われてもないのに自分から行動を起こすのが、出る杭であり、役割外行動である。 役割外行動をしたら許されないだろうな、あれこれ言われるだろうな、という雰囲気を感じ取ったせいで、 俺は役割外行動を思いとどまったわけだ。

俺らが何となく感じていた空気は、組織行動論で名前が付いてたんだな、と思う。 ぼんやりとした感覚に、理論という支柱を得た気分だ。

ソフトウェアエンジニアは上述のとおり、業務外での自己学習が多くなりがちである。 せっかく色々勉強する以上は、その勉強した成果が組織内での行動につながるほうが嬉しい。 そして、自己学習が組織内で活かせるような組織文化のほうがいいな、と思う。

*1:あとは、単純に楽しいから・面白いから、という理由もある。今回の本筋とは関係ないので割愛する。

役割外行動と組織市民行動について

組織行動論における「役割外行動(extra-role behavior)」についてまとめる。

主に「組織行動 (鈴木竜太・服部泰弘 著、有斐閣ストゥディア)」を参考にした。

役割外行動とは何か

役割外行動とは、「職務の範疇外の自発的・革新的な行動をすること」(組織行動 p.217)とされている。

英語で検索してみると、以下の定義が見つかった。出典はEXTRA ROLE BEHAVIOR

・Discretionary consent of an individual to behave beyond the formal lines of role expectation and work for the benefit and effectiveness of the organisation (Organ et al., 2006).
拙訳:個人が自己裁量を持つ中で納得し、役割の期待の正式な境界線を超えて行動し、組織の利益と効率のために働くこと。

・Activities that are discretionary in nature (such as helping others), which is not directly or explicitly required by the formal reward system, but does promote overall organizational efficiency (Becker and Kernan, 2003).
拙訳:自己裁量があるという性質を持つ(例えば他者を助けるなど)行動であって、正式な報酬体系が直接的や明示的に要求してはいないが、組織の全体的な効率を向上させるもの。

組織行動

組織において個人に求められる3つの行動とは何か

上記の「役割外行動」は、組織において個人に求められる3つの行動の一つである……と、組織行動には書いてある。3つの行動は以下の通りだ。

  • 組織に居続けること(参加)
  • 最低限のパフォーマンスを上げて、勤勉に働くこと(役割内行動)
  • 職務の範疇外の自発的・革新的な行動をすること(役割外行動)

この「参加・役割内行動・役割外行動」という3分類は私にとってなるほどと納得がいくものであった。(だから一度まとめておこうと思ったので、こうして書いている。) しかしながら、この3分類のフレームワークは、鈴木氏以外の本には登場しない。同じ作者の経営組織論(鈴木竜太 著、東洋経済)には載っているのだが、他の組織論の本を見ても登場しない。 ……鈴木氏独自の理論なんだろうか?

また、この3つの行動は何なのか、は、本の各部分によって微妙に言い回しが変わっている。「組織において個人(組織メンバー)に求められる行動(組織行動 p.6)」、「組織が存続し続けるために必要不可欠な行動(同書 p.217)」、「組織が生き残っていくために、組織で働く個人に求められる行動(経営組織論 p.99)」。まとめると、組織が存続するためには不可欠で、そのために個人が求められている行動、ということか。

組織市民行動とは何か

ところで、執筆時点で「役割外行動」とGoogle検索すると、最初に表示されるページは「組織市民行動」とは? - 『日本の人事部』である。
このページは、なんと「役割外行動」ではなく、「組織市民行動」を説明しているページである。

組織市民行動(organizational citizenship behavior)とは何だろうか。組織行動 p.219 によれば、以下の3つの特徴を持つ行動を組織市民行動と呼ぶ。

  1. 公式的には報酬に結びつかない
  2. 組織にとって有意義な行動
  3. 自らが必要であると判断して行う自己裁量的な個人行動

https://www.jstage.jst.go.jp/article/jaas1986/15/1/15_1_1/_pdf

なお組織市民行動という概念を最小に提唱したのは、Dennis Organという人らしい。OrganさんがOrganizationの研究をしてるのって面白くないですか

「役割外行動」とは何が同じで何が違うのだろうか。

先ほどの「組織市民行動」とは? - 『日本の人事部』では、以下のように書いている。

「組織市民行動」とは、企業や団体の従業員が自分の職務の範囲外の仕事をする「役割外行動」の一種で、英語ではOCB(Organizational Citizenship Behavior)と呼ばれます。

組織行動 p.7 でも同様に、「組織市民行動は、役割外行動の一部である」と書いてある。一方で、検索してみると以下の記述が見つかった。

役割外行動(extra-role behavior)かつてこの用語は、単に従業員が職務の範囲外の仕事をすることの意味で用いられていたが、最近では組織市民行動とほとんど同義に用いられていることもあり、意味的にはいくらか混乱を招いている。
https://www.jstage.jst.go.jp/article/jaas1986/15/1/15_1_1/_pdf

何だか、用語の意味が一定していないようだ。

役割外行動と組織市民行動の異同については、Organizational citizenship behavior - Wikipediaも参照されたい。

参考

一緒に働く人々を理解したい!――【自著を語る】『組織行動』 | レビュー | Book Bang -ブックバン-

#技術書典 7 買ったものまとめ

f:id:soratokimitonoaidani:20190929233340j:plain

2019年9月22日(日) 池袋サンシャインで開催された技術書典7に一般参加してきた。

前回(技術書典6)の記事はこちら。

linus-mk.hatenablog.com

ハマって覚えるデータ分析・機械学習の罠

初めて技術書典に出展して、新刊を300部売るまで - 天色グラフィティ
事前のチェックを全くしない状況で出かけたので、入場時に目星をつけていたのはこの本と「スクレイピング・ハッキング・ラボ 」のみであった。
Twitterのタイムラインに流れてきて存在を知って、「あー、機械学習系の実務に携わるなら買わなきゃ損だな」ってなった。
紙+PDF(1500円)の支払いは「かんたん後払い」限定と書いてあったけど、わざわざアプリをインストールするのが面倒だったので、 紙版(1000円)を現金で購入。PDFが欲しくなったらboothで別途買う予定。

Data Analysis Cheat Sheet

技術書展7にサークルとして参加します! - 筋肉で解決しないために。

本じゃなくてラミネート加工された紙なので、タイトルがよく分からない……
Data Analysis Cheat Sheet - data-analysis-cs - BOOTH に書いてあったものをタイトルとして記載しています。

実はbooth版は技術書典6のときに発行されていて、その時に買っている。しかし、買ったきり放置になっている。
この手のチートシートは物理版のほうが便利な気がする。

スクレイピング・ハッキング・ラボ

技術書典ではてなや増田をスクレイピングする薄い本を出します - はてな村定点観測所

そろそろスクレイピングのやり方をちゃんと勉強しといた方が良いかなと思ったので。

なお、「超お久しぶりです!実は私、はてなブックマークオフ会の会計です!」と声をかけようかと思ったが、
忙しそうだったのでやめておいてそのままその場を去った。
参考:はてブオフ会、運営と参加の感想を適当に書くよ 子供の落書き帳 Remix
というかこれ2014年か……5年も前か……月日が経つのは早すぎるぞ……

[第2版]Python機械学習プログラミング 達人データサイエンティストによる理論と実践


インプレスが安値で電子書籍を売っていたので、買ってしまった。
この本は、第1版の紙版を持っている。
確か、前回(6)は第2版を割引で売ってなかった。今回はありがたいことに安くなってたので購入。

Pythonスクレイピングの基本と実践 データサイエンティストのためのWebデータ収集術


そろそろスクレイピングのやり方をちゃんと勉強しといた方が良いかなと思ったので(2回目)。

株とpython

株で儲けらんないかなーとか思いつつ購入。 そういや全く別の売り場で「FXで1000万円ほど損したのを取り返す」っていうのがあったけど、FXはやってないので買ってません。

FXで1000万円溶かしてからの反撃 - とこしえ工房 - BOOTH

エンジニアアンチパターン NEXT

技術書典7にサークル参加した感想とふりかえり - このすみろぐ

技術書典5で出した本の加筆修正版。実は加筆前のも持っている(6で買った)わけだが、どうせならと改めて買う。

理論と実例で分かる自己肯定感

心理系の本は好きだ。あと自己肯定感がどこかに飛んでいくことがしばしばあるので購入。

理論と実例で分かるモチベーション

同上。

エンジニアの心を整える技術

上記は技術書典6でのツイート。当時は早々に売り切れてたよね、この本。
今回はだいぶ余っていたので無事に購入できた。
落ち込んだり凹んだりすることも多いので、この手の本には弱い。見るとつい買っちゃう。
(ここまで3冊並べると、大丈夫か俺の精神は、って思えてくるな……)

Slack App 開発ガイド

技書博で「SlackApps開発ガイド」を頒布します - mottox2 blog
7月の技書博で1冊、9月の技術書典7でもう1冊を発行している。すごいペースだ。
前者の方が初心者向けということなので、そちらを購入。slackbotで作ってみたいものがあるので買った。
個人開発系のモチベーションがほとんどないのをどうするかね……

読まれるコンテンツの作り方

「わかりやすい文章の書き方」は結構見かけたので、またかよと一瞬思ったのだが、少し違った。
ちょい切り口を変えてマーケティングに寄せたのが新鮮だなと思いつつ購入。

技術書典7にてデザインとコンテンツに関する新刊を2冊頒布します | ななうみいんふぉ
読まれるコンテンツの作り方 - SIGNIA - BOOTH

2階/3階の話

俺の覚えている範囲で記録に残しておく * 12:00のチケットで2階に入る(12:20頃?) * 機械学習とオーディオのエリアは重点的に見て、その他は一通り回って、気づいたら最奥部にいた * よく分からんけどこれが多分もう一つのフロアに行く列かな、と思いつつ、並んで、3階に上がる * 3階に知り合いの方がいて、話をしたら「2階のほうはすごい混んでるらしいですよ」と言われて「えー?そうなんですか?」と返した。このときは2階は混んでいて3階が空いているという認識が無かった。 * 2階に戻ることもなくそのまま3階から退場したので(14時前)、結局混み合う2階を見ることなく去った * 翌日以降に3階に人が来なかった・予想より売れなかったという言説を多数見かけて、思い返して書いたのがこれ↓

買ったはいいけど結局読むのか、の話

今回の技術書典7、行くかどうか結構迷っていた。

いやー。技術書典6で買った本を見返してみると、結局読んでない本が少なからずあることに気付いた。
今回も買ったはいいけど読んでません、だと意味がないよね……
白状すると、今回の最後の「読まれるコンテンツの作り方」の本は、自分で撮った画像を見て「あ、そうか?買ったっけ!?」って思ってしまった。ダウンロードカードだけは印象に残りにくいのか?
サークル参加側の人は技術書典の振り返り記事で「X部売れました!」と書いている。しかし、考えてみると、俺みたいに読まない人が多いと、実は読者が実際に読んだのはX部よりももっと少ないのかも、という問題がある。

それでは。

#pyconjp 2019 感想

(未完、後でもう少し加筆)

PyCon JP 2019に行った。
火曜日は業務があったので、今年は1日目のみ参加。
去年の感想はこちら。

linus-mk.hatenablog.com

資料や動画のリンクは以下を参照。

基調講演 Why Python is Eating the World

atmarkitによるレポートはこちら。
Pythonが世界を席巻している理由:PyCon JP 2019 第1日目 基調講演レポート:Pythonイベント - @IT

  • 初心者が学習しやすい
  • 企業側の需要が拡大している
  • pythonコミュニティ

「初心者が学習しやすい」の一例として、JavaPythonHello Worldのコードを比較していた。 「Javaの場合は色々な要素が出てくるから初学者にはわかりにくいけど、Pythonはprintするだけだから非常にシンプルでしょ?」という話を聞いて、 あぁこれJavaで「はじめてのプログラミング」を教えるのはキツイと思った話 - GoTheDistanceで見たやつだ!と思った。

最後にRaise your hand if you are going to commit to helping the Python comunity continue to grow? って講演者が言ってて、俺自身も手を挙げた。
さて自分がpythonコミュニティに貢献できること、何があるだろうか?
(貢献と言えば、スタッフ人数が足りてなさそうだから前日の会場設営を手伝った方がいいのかなと思いつつも、会場まで遠いので結局やめてしまった。)

Automate the Boring Stuff with Slackbot

Slackbotの作り方をはじめから丁寧に、という感じの講演。 作ってみたいSlackbotが一つあるんだけど、どうやっていいか分からず手を出せないでいるんだよね……

Using Python in Music Signal Processing, Speech Recognition and Intent Classification in Chatbot

個別の技術要素は分かったんだけど、全体としてどういうシステムが出来上がって何ができるのか今一つ分からず。
音声周りの技術は以前に業務で扱っていたので、音声・音響処理の知見は人よりもだいぶある。 大勢聴衆がいるはずなのに、ハッシュタグをみても関連するツイートがまるで見つからなかったので、解説ツイートをいくつかしてみた。

……ところで

日経新聞VTuberの話も中を見てみたら声質変換の話だし、音声信号処理のトークの需要は一定数あったりするんだろうか。

Python による日本語自然言語処理 〜系列ラベリングによる実世界テキスト分析〜

ListはIteratorですか?

この手の型の話は

運営の良かった点

去年は小部屋(6回の会議室)がすぐにいっぱいになった。防火上の理由か何かで6階の部屋は立ち見がでないので、それ以上入ることもできず、大勢の人が希望の講演を聞けなかった。
今年は6階の隣接する2部屋を同じセッションにして、1つの部屋のトークの映像をもう片方の部屋に中継していた。これによって定員の不均衡はある程度解消されたので、良かった。

良かった点と言いつつ改善すべき点を書いてしまうと、このときの隣室で流すトークの音量が小さくてなかなか聞こえなかったので、 もう少し大きい音が出るとありがたい。

まとめ/おまけ

次にやること:

  • pythonコミュニティが成長するのを助けるために貢献する方法を考える(from 基調講演)
  • (from Automate the Boring Stuff with Slackbot)
  • (from Python による日本語自然言語処理 〜系列ラベリングによる実世界テキスト分析〜)
  • (from ListはIteratorですか?)