pandas DataFrameをエクセルで開いても文字化けしないcsvファイルに書き出す

pandasのDataFrameをファイルに保存したい時、
to_csvやto_excelなど、とても便利なメソッドが用意されています。

pandas.DataFrame.to_csv
pandas.DataFrame.to_excel

ただ、日本語文字を含むデータフレームをto_csvで書き出すと、
それをエクセルで開いたときに文字化けしてしまいます。
(他職種のメンバーに連携するとき非常に厄介な現象です。)

エクセルで開きたいなら to_excel() を使えばいいので、普段はそれでクリアしているのですが、
データ量やその後の用途の問題で、csvファイルで要求されるが、その人はエクセルでも使うといったパターンがあります。

このような時は、 encoding="utf-8_sig"を指定することで文字化けしないようにできます。
(pandasにとってExcelはスコープ外だからか、公式ドキュメントにはこの辺りのことを明記している記述は見つかりませんでした)


import pandas as pd
df = pd.DataFrame(
        {
            'col1': ["あ", "い", "う", "え", "お"],
            'col2': ["か", "き", "く", "け", "こ"],
        }
    )
df.to_csv("export_1.csv", index=None)
df.to_csv("export_2.csv", encoding="utf-8_sig", index=None)

# jupyter で実行しているので、!をつけることでBashコマンドを実行
!ls -la *.csv
-rw-r--r--@ 1 yutaro  staff  50  5 25 01:25 export_1.csv
-rw-r--r--@ 1 yutaro  staff  53  5 25 01:25 export_2.csv

2つのファイルを見比べると、 encoding=”utf-8_sig” をつけた方は 3バイトファイルサイズが大きいことがわかります。
これは、BOM(バイトオーダーマーク)と呼ばれる情報が付加されたためで、
これによって、 export_2.csv の方はExcelで開いても文字化けしなくなります。
(export_1.csv は文字化けします。)

matplotlibでバイオリン図

データの可視化方法として、バイオリン図というものがあります。
バイオリン図 – Wikipedia

pythonでこれを書こうと思ったら、 Seaborn を使うのが定番なのですが、
実はmatplotlibにもAPIが用意されていたことを知ったのでその紹介です。

ドキュメント
matplotlib.axes.Axes.violinplot
(ただ、どうも Seaborn の方が使いやすそう。)

とりあえず動かしてみましょう。データは手頃なところで、 iris の4つの特徴量を可視化してみます。


import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
data = load_iris().data
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, title="iris data")
ax.violinplot(data)
plt.show()

出力はこちら。

先ほどのドキュメントに記載されている通り、他にも細かなオプションで見た目が調整できるのですが、
Seaborn の方が多機能のようです。
バイオリンの左右に違う分布を表示するといったことを行いたかったのですが、
どうやらmatplotlibではできなさそう。

MeCabの出力フォーマット

しばらくふれない間にまたど忘れしてしまったので、MeCabの出力フォーマットのメモです。

公式サイトの使い方 に書いてあります。

表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音

よくある例の「すもももももももものうち」を形態素解析してみても * が多くてわかりにくいので、
先の公式ページの説明を読んだ方が早いです。


~$ mecab
すもももももももものうち
すもも	名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
の	助詞,連体化,*,*,*,*,の,ノ,ノ
うち	名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS

一通り例が見たい場合、*になってばかりでなかなか登場しないのが品詞細分類3ですが、
文章に地名や人名が含まれている時に登場するので、次のような文章はいかがでしょうか。


~$ mecab
渋谷で働くデータサイエンティスト
渋谷	名詞,固有名詞,地域,一般,*,*,渋谷,シブヤ,シブヤ
で	助詞,格助詞,一般,*,*,*,で,デ,デ
働く	動詞,自立,*,*,五段・カ行イ音便,基本形,働く,ハタラク,ハタラク
データ	名詞,一般,*,*,*,*,データ,データ,データ
サイエンティスト	名詞,一般,*,*,*,*,サイエンティスト,サイエンティスト,サイエンティスト
EOS

自分は表層形、品詞、原形をよく使うので、
‘\t’でsplitした結果の、index 0 が、表層形、
index 1をさらに’,’ split して、 index 0 が品詞、index 6が原型、
ってのだけ把握していればなんとかなることが多いです。

それで、適当なテキストを試しに形態素解析して、
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
と出てきて、何番目が原型だ?? となって公式サイト見に行く、ということを何度もやらかしています。

pipでライブラリのバージョンを指定してインストール

pipでライブラリのバージョンを気軽にあげていたら、動かなくなるものが出たので戻し作業をやりました。
良い機会なので、pipで指定したバージョンのライブラリをインストールする方法を紹介します。

方法は、ドキュメントの、examplesの中にあるように、ライブラリ名の後ろに==でつなげてバージョンを指定するだけです。
pip install – examples

ちなみに、今回動かなくなったのは statsmodels です。(バージョンを上げたのはscipy)


# 動かなくなったコード。 ただのインポートさえできなくなった。
import statsmodels.api as sm

# 出力されたエラー
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
 in ()
      1 import numpy as np
      2 import matplotlib.pyplot as plt
----> 3 import statsmodels.api as sm

~/.pyenv/versions/anaconda3-5.2.0/lib/python3.6/site-packages/statsmodels/api.py in ()
     14 from . import robust
     15 from .robust.robust_linear_model import RLM
---> 16 from .discrete.discrete_model import (Poisson, Logit, Probit,
     17                                       MNLogit, NegativeBinomial,
     18                                       GeneralizedPoisson,

~/.pyenv/versions/anaconda3-5.2.0/lib/python3.6/site-packages/statsmodels/discrete/discrete_model.py in ()
     43 
     44 from statsmodels.base.l1_slsqp import fit_l1_slsqp
---> 45 from statsmodels.distributions import genpoisson_p
     46 
     47 try:

~/.pyenv/versions/anaconda3-5.2.0/lib/python3.6/site-packages/statsmodels/distributions/__init__.py in ()
      1 from .empirical_distribution import ECDF, monotone_fn_inverter, StepFunction
----> 2 from .edgeworth import ExpandedNormal
      3 from .discrete import genpoisson_p, zipoisson, zigenpoisson, zinegbin

~/.pyenv/versions/anaconda3-5.2.0/lib/python3.6/site-packages/statsmodels/distributions/edgeworth.py in ()
      5 import numpy as np
      6 from numpy.polynomial.hermite_e import HermiteE
----> 7 from scipy.misc import factorial
      8 from scipy.stats import rv_continuous
      9 import scipy.special as special

ImportError: cannot import name 'factorial'

statsmodelsがインポートできないので、statsmodelsを疑ってしまいそうですが、
根本的な原因は、scipyから、 factorialをインポートできなかったことでした。

----> 7 from scipy.misc import factorial

最近、scipyのバージョンを 1.1.0から 1.3.0 へ上げたのが怪しいです。
真の原因は何か他にありそうな気もするのですが、とりあえずscipy のバージョンを戻します。

戻し手順は最初に対象のライブラリをアンインストールした後に、再度バージョン指定してインストールです。


$ pip uninstall scipy
Uninstalling scipy-1.3.0:
# --- 略 ---
Proceed (y/n)? y
  Successfully uninstalled scipy-1.3.0

$ pip install scipy==1.1.0
# --- 略 ---
Installing collected packages: scipy

これでscipyのバージョンが戻り、再びstatsmodelsをimport できるようになりました。

pandasのデータフレームから重複行を削除する

前回の記事が重複行の抽出だったので今回は重複行の削除です。
参考:pandasのデータフレームの重複行を抽出する

このあと専用の関数を紹介しますが、
重複行の抽出条件を反転させればできてしまうので、この書き方でも構わないと思います。
print(df[~df.duplicated()])
(むしろ、duplicated関数の引数keepの意味はこちらの方がわかりやすい。)


import pandas as pd
import numpy as np

# データの作成
df = pd.DataFrame(
        {
            "col0": np.random.choice(["A", "B", "C"], size=10),
            "col1": np.random.choice(["a", "b", "c"], size=10),
            "col2": np.random.choice(["1", "2", "3"], size=10),
        }
    )
# データの確認
print(df)
'''
  col0 col1 col2
0    C    a    1
1    B    a    2
2    A    c    3
3    B    c    1
4    B    a    2
5    C    a    1
6    C    b    2
7    B    a    2
8    C    c    3
9    C    c    3
'''
# duplicated()の結果を反転させると重複していない行を抽出できる。
print(df[~df.duplicated()])
'''
  col0 col1 col2
0    C    a    1
1    B    a    2
2    A    c    3
3    B    c    1
6    C    b    2
8    C    c    3
'''

pandasには重複行削除専用のメソッドとして、drop_duplicatesが定義されています。
ドキュメントはこちら。
pandas.DataFrame.drop_duplicates

引数の keep と subset は duplicated と同じように使えます。
また、inplace に Trueを指定することで、そのデータフレームの値自体を書き換えます。
デフォルトはFalseで、重複行を削除した結果を返します。


print(df.drop_duplicates())
'''
  col0 col1 col2
0    C    a    1
1    B    a    2
2    A    c    3
3    B    c    1
6    C    b    2
8    C    c    3
'''

先ほどの結果と同じもののが得られましたね。

pandasの実装を見るとわかるのですが、ただのラッパーなので、
とくにこちらの方が実行速度が速いといったことはなさそうです。
https://github.com/pandas-dev/pandas/blob/v0.24.2/pandas/core/frame.py#L4605-L4637

pandasのデータフレームの重複行を抽出する

データフレームに入ったデータについて、重複がないか確認したい場面は結構あると思います。
僕の場合は、そういう時はSQLでデータを抽出する段階でユニークにしてしまうことが多いです。
また、特定の列の値(idなど)の一意性の確認であれば、value_counts()して、2個以上含まれている値が無いか見たりします。
それ以外のケースでも、groupbyやsetなど使ってゴリゴリコードを書いてどうにかすることが多いのですが、
せっかく専用の関数が用意されているので今後はそれを使うようにしたいです。

ということで、今回はduplicated()の紹介です。
ドキュメントはこちら。
pandas.DataFrame.duplicated

pythonを勉強し始めた頃、引数なしで実行して、
出力が直感的でなくて使いにくいなーと思っていたのですが、subsetやkeepなどの引数をきちんと理解すれば非常に便利です。

とりあえず実験するために、ダミーデータを作っておきます。


import pandas as pd
import numpy as np

df = pd.DataFrame(
        {
            "col0": np.random.choice(["A", "B", "C"], size=10),
            "col1": np.random.choice(["a", "b", "c"], size=10),
            "col2": np.random.choice(["1", "2", "3"], size=10),
        }
    )

print(df)
'''
出力 (乱数を使っているので実行するたびに変わります。)
  col0 col1 col2
0    B    b    1
1    C    c    2
2    A    b    1
3    B    a    2
4    A    b    1
5    C    b    3
6    A    b    1
7    B    b    1
8    A    b    3
9    B    b    3
'''

このデータフレームに対して、引数無しで実行したものがこちらです。


print(df.duplicated())
'''
0    False
1    False
2    False
3    False
4     True
5    False
6     True
7     True
8    False
9    False
dtype: bool
'''

これ、一見、インデックス4,5,6の行が重複してるという意味に勘違いしそうなのですがそうではありません。
引数を省略すると、keep="first"を指定したことになり、重複行のうち、最初の値はFalseになります。
なので、インデックス4の行と重複してる行が0~3の間にあるという意味です。(実際はインデックス2)

keep="last"を指定すると、逆に重複している行のうち、
最後の行はFalse、それ以外の行はTrueになります。(重複してない行はFalse)
こちらの方が、時系列に並べたデータのうち、最新のデータを取りたい場面などで重宝すると思います。
また、 subsetに列名の集合を渡すと、その列だけを使って判定を行います。
これもまとめて試してみましょう。


print(df.duplicated(subset=["col1", "col2"], keep="last"))
'''
0     True
1    False
2     True
3    False
4     True
5     True
6     True
7    False
8     True
9    False
dtype: bool
'''

重複した行全部を抽出したい、という場合は、keep=Falseを指定します。
また、先に紹介した2例でもそうなのですが、実際に使う時は重複した行のインデックスではなくて、
その行そのものをみたいという場面が多いので、次のような使い方になると思います。


print(df[df.duplicated(subset=["col1", "col2"], keep=False)])
'''
  col0 col1 col2
0    B    b    1
2    A    b    1
4    A    b    1
5    C    b    3
6    A    b    1
7    B    b    1
8    A    b    3
9    B    b    3
'''

df[]の中に放り込んであげるだけですね。
コードのテスト時など、無いはずの重複が本当に無いことを確認する時などは、
duplicated関数は結構便利です。

重複を除外する時などはまた専用の関数があるので次に紹介します。

白金鉱業 Meetup Vol.7 に参加しました

先日ブレインパッドさんのオフィスで開催された、白金鉱業 Meetup Vol.7 に参加してきました。
Vol.4以来、久しぶりの参加です。
今回は機械学習のテクニカルな点以外にも非常に面白い話を聞くことができ、マジで参加してよかったです。
今回もメモした内容などまとめておきます。

MLOps Yearning ~ 実運用システムを構築する前にデータサイエンティストが考えておきたいこと


楽天株式会社/三浦航さん

MLOpsや機械学習プロジェクトのナレッジは蓄積されているが、データサイエンスにおける継続的なモデルの改善部分のナレッジは薄い(と感じられていること)から問題提起されてスタート。
データサイエンスがメインフィールドのデータサイエンティストが機械学習モデルを構築するときに
考えておくべきところについてお話されました。
題材として取り上げられたのは、店舗名からそのカテゴリーを予測する自然言語処理タスク。
その他、ショッピング、オークションサイトにおける同一アイテムの名寄せ、レシピサイトにおける材料名の正規化なども例示されましたが、
似たようなタスクには僕もよく直面し、毎回色々工夫しながら対応しているので興味深く聞きました。

楽天さんも独自の機会学習基盤を持っていて、その上でAirflowが動いてるそうです。(うらやましい)

– 学習したモデルは即座に本番に反映されるのではなく、次回の実行で反映されるフローにしていて、その間に学習したモデルのチェックをする猶予時間を作っている
– 機械学習パイプラインは機械学習エンジニアが実装することになっているが、 データサイエンティストも関わった方がいいのではないか。
– そもそも店舗カテゴリーの予測タスク自体が難しい。~~薬局は機械学習モデルでドラッグストアだとわかるが、ユニクロやH&Mは事前に知っていないと何のお店かわからない。
固有名詞が多く、分かち書きも難しいく、学習時と運用時のデータも異なる。
– トレンドなどによりデータの傾向が毎回変わる。
– タスクの難易度が変わるので、正解率やf1スコアなどをラッキングしていても意味がないことがある。
– データを一個一個見る定性的な評価も行なっている。
– ラベル付けされたデータのカテゴリの分布変化や、同様に予測されたカテゴリの分布変化も見る。
– ルールベースで対応できることはルールベースで対応する。
– 一回のPoCだけで運用にのせるのは難しいので、ヒストリカルなデータで複数回結果を見る必要がある。
– 実運用を見据えて、実用上やりたいことでPoCを回すことが大事(そのためメニビジネスフローを明確にしておく)
– データサイエンティストが考慮すべき問題の多くは one-shotのPoCというのが問題で、時間軸と業務フローの観点が欠如していることに起因する。
– データサイエンティスト、機械学習エンジニア、PMなどが、お互いの領域をカバーする必要あり。

特に、機械学習モデルもヒストリカルデータを使って複数の期間でバックテストするべき、という観点は自分には抜けていたので新鮮でした。
(トレーダーとしては、この問題にはかなり慎重に取り組んでいて、
いろんな期間でバックテストしているのに機械学習モデルになるとなぜか全くやってませんでした。)

また、トラッキングしてる指標が悪化したときに、タスクの難易度については考慮できてなかったので、
今後はそれも含めて業務にあたろうと思います。

ディープラーニングによるくずし字認識

人文学オープンデータ共同利用センター/カラーヌワット・タリンさん

ディープラーニングの話題に入る前に、くずし字の歴史や、その課題の意義や難しさについて説明していただき、
そこが非常に面白かったです。(資料がまだ公開されていないのが残念)

日本に漢字が入ってきてから、明治の小学校令があるまで1000年以上にわたってくずし字が使われてて、
現在、古典籍が300万点、古文書が1億点あるっていう基本的なところから初めて知りました。
現在、画像データに変換して保存が進められているそうですが、
画像だと検索もできないので、うまくアクセスできないという課題があるそうです。
ということでディープラーニングで文字データを抽出されています。

実例の画像を見ながら、その課題の難しさなどを説明されていましたが、どう考えても通常の手書き文字より難しい。
– 同じ文字なのに複数の書き方がある。(母字が異なるなど)
– 違う文字なのにとても似ているものがある。物によってはサイズが違うだけなど。
– 重なって書かれる文字がある。
– 別ページの文字が透けていたりもする。
– レイアウトが様々でどこから読み始めるのかも難しい。(色の濃い順に読むなど)
– ページ内に絵も入ってる。

ということで、一般的な文字認識の手順がつかえず、
画像から文字へ変換する End to Endの KuroNetというモデルを作られたそうです。

f1スコアは0.8くらいだそうですが、ほぼ完璧に判定出てきている文字もあれば、
データセットの中に1回しか出てこない漢字など、全く判定できないものもあるそうです。
もともと専門家でなければ読めないので、教師データを作るのにもコストが高く大変だった様子。

データセットは公開されているので近々挑戦してみたいです。
参考:日本古典籍くずし字データセット

AIチームのチームビルディングについて

エムスリー株式会社/西場正浩さん

最近、各所のミートアップでよく見かける西場さん。
じつは、今回はこの話を聞くために参加を申し込みました。
(AIや機械学習ではなく、BIがメインのアナリストチームという違いがありますが、
自分は今もチームビルディングに苦戦しているので。)

最初にエムスリーの機械学習チームがここ一年で知名度を上げられたという話をされていました。僕自身も、1年前は知らなかったと思います。

AIチームに配属と聞いて入社してみたが、入ってみたら自分しかいなかった、
というところから始まって、今のチームができががるまでの取り組みを話していただきました。

– “チームとは目的に向かって活動する集団”
なので、まずはそのチームの目的を定める必要があります。
目的の次に目標を定める。
– 株式会社である以上、お金を稼ぐことは重要で、お金を稼ぐチームであれば会社もそこに投資してくれるので人を増やせるし給料も上がる。

この辺りは非常に基本的なことなのですが、なかなか意識できてないことが多いですね。気をつけないと。

– 目標と目的が決まったら採用開始というのは良くない。
まずは現状の把握をする必要があり、目標や目的が同じであっても現状が違えば必要な人もスキルも全然違う。
たとえば、機械学習で成果を出すために必要なスキルも状況によって変わる。
課題を発見できる人
MLの問題に落とし込める人
モデル作れる人
モデルをデプロイできる人
機械学習基盤を作れる人
MLのプロジェクト全体をマネジメントできる人
MLのプロダクトをマネジメントできる人 など

– 人を集めるにはどうするか。 外部から採用する/内部から採用する
機械学習エンジニアになりたい人は社内にもいたりするという話でしたが、
確かにそれはそうだと思います。
職種を変えるための転職って、実は効率悪いと思うので社内での採用というも考えたいですね。

– 外部から人を集められてない理由をきちんと考える。

ここは4Pや、AISASなどのフレームワークを活用されたそうです。
AISASは初めて知りましたが、以下の頭文字のようです。
・A:Attention(認知・注意)
・I:Interest(興味)
・S:Search(検索)
・A:Action(購買)
・S:Share(情報共有)

4Pの説明の方では特に、
Productの
「誰と働くのか、あなたと働くことは魅力的なことなのか?」
という話が一番どきっとしました。

正直、事業内容や社内のデータの充実度や面白さ、会社の働きやすさ、他チームのメンバーの魅力は他社に引けを取らないと思っているのですが、マネージャーである自分に魅力があるかどうかというのが一番自信がない。

残りの3Pについては内容を紹介しておくと 
Price
給料、福利厚生などの対価は良いのか。
(みなし残業とか、年収のうちボーナスが占める割合が高くないかとか、
 人によっては”なし!”と判断される短所がないか)

Place
どこで採用活動するのか。

Promotion
ターゲット層にその求人情報が届いているのか。

それぞれとても重要だと思います。

– MLエンジニアの最低条件としては次の二つを挙げられていました。
1. 年間60本以上の論文を読んでいる。
2. そのうち6本以上を追試している。
(noteにも書かれています。)

自分のチームでも、こういう条件を設定するべきかの議論はあるのですが、やっぱり必要そうですね。
自分自身が未経験の状態で採用してもらったというのもあり、次の未経験者にもちゃんをチャンスを渡したい、っていう個人的な思いもがあるのですが、
その人のキャリアに責任を持てるか、という観点でいうと論文読めない人には機械学習を任せられないというのは理解できます。
(アナリストであれば、論文は読んでいなくてもちゃんと成果を上げてくれている人もいるのですが。)

– オンボーディングの完了基準は外部から認められる結果を出したこと。
チームに馴染んだなどの理由で完了としない。

これもとても重要だと思います。チームに馴染んだどころか、単純に期間で区切って終わりにするようなやり方ではとてもうまくいかないですし、逆に計画より短期間で活躍しだした人に過剰なフォローも不要だと実感してます。

– メンバーみんなをプロとして尊重する。
– モチベーションは本人に任せ、モチベーションコントロールなどはしない。
– 一方的な教育もROIが見合わなければしない。(見合うならする)
(この他、オフレコの話が少々)

正直、自分がメンバーのモチベーションマネージメントに四苦八苦しているので羨ましい気もしました。
しかし、まだ自分が自分のチームのメンバーをきちんとプロとして尊重してあげられてない事実もあり、接し方を改善していく必要はあります。

資料だけひとり歩きしてしまうと良くないということで今回の資料は非公開ですし、
実際メモを見てみると一見厳しいようにも見えます。
でも、会場で話を聞いていた限りでは、メンバーをきちんと尊重して、
良いチームを作り上げられているように感じました。
これまでも複数のミートアップで西場さんの発表を見ていますが、非常に尊敬できる方なので、メンバーのモチベーションコントロールはしてないのではなく、
必要な状況があまり発生してないのではないかとも感じました。

まとめ

久々に予定が合った(抽選は落選したのですがギリギリ前日に繰り上がった)ので参加できましたが、今回はどれも内容が濃くて面白い発表で本当にラッキーでした。
オフレコになったので記事中書きませんでしたが、
今まさに一番悩んでる内容についてもご意見を聞けたのも良かったです。

最後に次回の登壇者の予告もありましたが、
とても楽しみな方々だったので、可能な限り予定を調整して参加したいです。

pandasで日時を表す文字列を時刻型に変換

前回の記事の予告通り、
pandasのto_datetime関数の紹介です。

pandas.to_datetime

非常に多くのデータ型や、フォーマットに対応していて柔軟に時刻データに変化してくれます。
ドキュメント中に書かれている引数:argの通り、Seriesでも一個の文字列でも大丈夫です。

Parameters:
arg : integer, float, string, datetime, list, tuple, 1-d array, Series
New in version 0.18.1: or DataFrame/dict-like

実際に使ってみましょう。


import pandas as pd
pd.to_datetime("2019/05/17 07:25:34")
# Timestamp('2019-05-17 07:25:34')

pd.to_datetime("2019-05-17 07:25:34.372245")
# Timestamp('2019-05-17 07:25:34.372245')

pd.to_datetime("2019 May 17  07:25:34.372245")
# Timestamp('2019-05-17 07:25:34.372245')

pd.to_datetime("17-05-19 07:25:34")
# Timestamp('2019-05-17 07:25:34')

上の例ではフォーマットを変えながら文字列を渡しましたが、いい感じに解釈してくれているのがわかります。
%Y-%m-%dとか指定しなくていいのでとても楽です。

これがあるので、自分はstrptimeはほぼ使っていません。

文字列を一つ渡せば、Timestampが戻り、Seriesを渡せばSeriesが帰ってきますが、
listを渡した時はlistではなく、DatetimeIndexが返されるのは注意です。

あとは、Timestamp型と、datetime型の違いがきになるところですが、
ほぼ互換性があると書いてあるので恐らく大丈夫でしょう。
(細かな違いもそのうち調べようとは思っていますが。)

参考: pandas.Timestamp

Timestamp is the pandas equivalent of python’s Datetime and is interchangeable with it in most cases. It’s the type used for the entries that make up a DatetimeIndex, and other timeseries oriented data structures in pandas.

pythonで日付を表す文字列をdatetime型に変換する

自分は滅多に使わないのですが、前回の時期で strftime を紹介したので、
その逆の変換を行う strptime も紹介しておきます。

参考:pythonで今日の日付を表す文字列をつくる
前の記事中にも少し書いてますが、strptime を使おうとすることよりも、strftimeと間違えて書いてしまうことが多いです。

ドキュメントはこちら。
lassmethod datetime.strptime(date_string, format)

書いてある通り、日時を表す文字列と、そのフォーマットを渡してあげるとdatetime型に変えてくれます。
使い方のイメージ。


import datetime
dt = datetime.datetime.strptime("2019-08-01 07:31:25", "%Y-%m-%d %H:%M:%S")
dt
#  datetime.datetime(2019, 8, 1, 7, 31, 25)
print(dt)
# 2019-08-01 07:31:25

フォーマットを指定するのが面倒ですね。

%Yや%mなど、使える文字の一覧はこちらにあります。
strftime() と strptime() の振る舞い

個人的な感想としては、あまり使い勝手が良くないので、
次の記事で紹介する、pandasのto_datetime関数を採用することが多いです。
(結果の型がTimestampなので、完全に互換なものではないのですが、実用上これで困らない。)

pythonで今日の日付を表す文字列をつくる

プログラミングの小ネタです。
集計結果をファイルに保存するときに、ファイル名に日付を入れておくことがあります。
コード中にハードコーディングして動かすたびに書き換えてもいいのですが、
普通は自動的に今日の日付が入るようにしておいたほうが楽なのでその方法を紹介します。

これは標準ライブラリの datetime で実現できます。
ドキュメントはこちら
datetime — 基本的な日付型および時間型
datetimeの中にもう一回datetimeが作られているとか、色々文句を言いたくなることもあるのですが、
時間処理に必要なことは大抵やってくれます。

実行美の日付を得るには、
datetime.datetime.today() か、 datetime.datetime.now() で現在時刻を取得して、
strftime() メソッドで、フォーマットを指定して表示するのが丁寧だと思います。


import datetime
today = datetime.datetime.today().strftime("%Y-%m-%d")
print(today)
# 2019-05-15

この方法でなんの問題もないのですが、
strftime() が strptime() と間違えやすかったり、フォーマット指定の文字列が大文字だったか小文字だったかド忘れしたりするので、
面倒な時は .date() メソッドで日付型にして時刻情報を捨て、 str()関数で文字列型にするという雑な方法でやっています。


today = str(datetime.datetime.today().date())
print(today)
# 2019-05-15

.date() を外すと、時刻まで出力されるのですが、空白が入るのでファイル名には使いにくくなります。
ただ、ロギングが目的の場合は時刻まであったほうが便利でしょう。