パンダは日付を自動的に認識できますか?


151

今日、私は、データファイル(たとえば)からデータを読み取るときに、パンダが値のタイプを認識できるという事実に積極的に驚きました。

df = pandas.read_csv('test.dat', delimiter=r"\s+", names=['col1','col2','col3'])

たとえば、次の方法で確認できます。

for i, r in df.iterrows():
    print type(r['col1']), type(r['col2']), type(r['col3'])

特に整数、浮動小数点数および文字列は正しく認識されました。しかし、次の形式の日付を持つ列があります2013-6-4。これらの日付は文字列として認識されました(pythonの日付オブジェクトではありません)。認識された日付までパンダを「学習」する方法はありますか?


この種のバージョン依存の質問については、常にパンダのバージョンを述べてください。2013
smci

また、dtypeは列ごとに固定されてdf.iterrows()いるため、1行ごとに繰り返して表示する必要はありませんdf.info()
smci

回答:


326

を追加するparse_dates=Trueparse_dates=['column name']、読み取る場合は通常、魔法のように解析するのに十分です。しかし、手動で定義する必要がある奇妙なフォーマットが常にあります。そのような場合、可能な限り最も柔軟な方法である日付パーサー関数を追加することもできます。

文字列を含む「datetime」列があるとします。

dateparse = lambda x: pd.datetime.strptime(x, '%Y-%m-%d %H:%M:%S')

df = pd.read_csv(infile, parse_dates=['datetime'], date_parser=dateparse)

このようにして、複数の列を1つの日時列に結合することもできます。これにより、「日付」列と「時間」列が1つの「日時」列にマージされます。

dateparse = lambda x: pd.datetime.strptime(x, '%Y-%m-%d %H:%M:%S')

df = pd.read_csv(infile, parse_dates={'datetime': ['date', 'time']}, date_parser=dateparse)

このページstrptimestrftime 、ディレクティブ(つまり、さまざまな形式で使用される文字)を見つけることができます


8
うまくいきませんでした。次のエラーが発生しました:TypeError: strptime() argument 1 must be str, not float
Jean Paul

6
データフレームにnanがあったため、このエラーが発生しました。
ジャンポール

解析不可のマテリアルまたはNaNまたは/ NsもNaTするアイテムを追加できますか。このようなパーサーが存在する場合、このパーサーは列全体を完全にスキップするようです
Amir

オプションがありますinfer_datetime_format:「パンダは列の日時文字列の形式を推測しようとします」。これはの代わりに使用できますdate_parser
Winand 2018年

1
日付がISO 8601形式である場合、infer_datetime_formatまたはパーサー関数を渡すべきではないことに注意してください-パンダにそれを処理させるよりもはるかに遅いです(特に後者)。この回答の日付形式もこのカテゴリに該当します
Mr_and_Mrs_D

20

@Rutgerが応答してからパンダインターフェイスが変更された可能性がありますが、私が使用しているバージョン(0.15.2)では、date_parser関数は単一の値ではなく日付のリストを受け取ります。この場合、彼のコードは次のように更新する必要があります。

dateparse = lambda dates: [pd.datetime.strptime(d, '%Y-%m-%d %H:%M:%S') for d in dates]

df = pd.read_csv(infile, parse_dates=['datetime'], date_parser=dateparse)

11

pandas read_csvメソッドは日付の解析に最適です。http://pandas.pydata.org/pandas-docs/stable/generated/pandas.io.parsers.read_csv.htmlにある完全なドキュメント

異なる列に異なる日付の部分を持ち、パラメーターを渡すこともできます。

parse_dates : boolean, list of ints or names, list of lists, or dict
If True -> try parsing the index. If [1, 2, 3] -> try parsing columns 1, 2, 3 each as a
separate date column. If [[1, 3]] -> combine columns 1 and 3 and parse as a single date
column. {‘foo : [1, 3]} -> parse columns 1, 3 as date and call result foo

日付のデフォルトの検知はうまく機能しますが、北米の日付形式に偏っているようです。あなたが他の場所に住んでいる場合、あなたは時々結果に引っかかるかもしれません。私が覚えている限り、2000年1月6日は、私が住んでいる6月1日とは対照的に、米国では1月6日を意味します。23/6/2000のような日付が使用される場合、それらを振り回すのに十分スマートです。ただし、日付のYYYYMMDDのバリエーションを使用する方が安全です。ここでパンダの開発者に謝罪しますが、私は最近、現地の日付でテストしていません。

date_parserパラメータを使用して、形式を変換する関数を渡すことができます。

date_parser : function
Function to use for converting a sequence of string columns to an array of datetime
instances. The default uses dateutil.parser.parser to do the conversion.

2
dayfirstヨーロッパ/国際的な日付にはTrueを指定できます。pandas.pydata.org/pandas-docs/stable/generated/...
ウィル・ゴードン

10

pandas.to_datetime()のドキュメントで推奨されているpandas.read_csv()とおりに使用できます。

列またはインデックスに解析できない日付が含まれている場合、列またはインデックス全体が変更されずにオブジェクトデータ型として返されます。非標準の日時解析には、pd.to_datetimeafterを使用しpd.read_csvます。

デモ:

>>> D = {'date': '2013-6-4'}
>>> df = pd.DataFrame(D, index=[0])
>>> df
       date
0  2013-6-4
>>> df.dtypes
date    object
dtype: object
>>> df['date'] = pd.to_datetime(df.date, format='%Y-%m-%d')
>>> df
        date
0 2013-06-04
>>> df.dtypes
date    datetime64[ns]
dtype: object

オブジェクト型である他の列も日付に変換しています
ratnesh

10

2つの列を1つの日時列にマージすると、列が個別にdate_parser関数に送信されるため、受け入れられた回答はエラー(pandasバージョン0.20.3)を生成します。

次の作品:

def dateparse(d,t):
    dt = d + " " + t
    return pd.datetime.strptime(dt, '%d/%m/%Y %H:%M:%S')

df = pd.read_csv(infile, parse_dates={'datetime': ['date', 'time']}, date_parser=dateparse)

1
私はパンダ0.22を使用していますが、受け入れられた回答が機能しないことに同意します。

これにより、「TypeError:strに連結できるのはstr(「float」ではない)のみです」が生成されます。Date列はd / m / y、time列はH:M:00
IceQueeny

8

はい- pandas.read_csv ドキュメントによると:

注:iso8601形式の日付には高速パスが存在します。

したがって、csvという名前の列がdatetimeあり、日付が2013-01-01T01:01たとえば次のようになっている場合、これを実行するとパンダ(v0.19.2を使用しています)が日付と時刻を自動的に取得します。

df = pd.read_csv('test.csv', parse_dates=['datetime'])

を明示的に渡す必要があることに注意してくださいparse_dates。そうしないと動作しません。

確認:

df.dtypes

列のデータ型が datetime64[ns]


あなたはその質問を誤解していると思います。ユーザーは、文字列の形式に対してオプションを有効にできるかどうかを知りたいと考えています。
Arya McCarthy

@AryaMcCarthyうーん、彼は基本的に日付が正しく認識されることを望んでいるので、パンダによって自然に認識されるようにソースデータを変換する方法について言及しています。彼はどこにも、ソースデータの形式を変更できないと述べていません。
Gaurav

1

パフォーマンスが重要な場合は、時間を確保してください。

import sys
import timeit
import pandas as pd

print('Python %s on %s' % (sys.version, sys.platform))
print('Pandas version %s' % pd.__version__)

repeat = 3
numbers = 100

def time(statement, _setup=None):
    print (min(
        timeit.Timer(statement, setup=_setup or setup).repeat(
            repeat, numbers)))

print("Format %m/%d/%y")
setup = """import pandas as pd
import io

data = io.StringIO('''\
ProductCode,Date
''' + '''\
x1,07/29/15
x2,07/29/15
x3,07/29/15
x4,07/30/15
x5,07/29/15
x6,07/29/15
x7,07/29/15
y7,08/05/15
x8,08/05/15
z3,08/05/15
''' * 100)"""

time('pd.read_csv(data); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"]); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
     'infer_datetime_format=True); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
     'date_parser=lambda x: pd.datetime.strptime(x, "%m/%d/%y")); data.seek(0)')

print("Format %Y-%m-%d %H:%M:%S")
setup = """import pandas as pd
import io

data = io.StringIO('''\
ProductCode,Date
''' + '''\
x1,2016-10-15 00:00:43
x2,2016-10-15 00:00:56
x3,2016-10-15 00:00:56
x4,2016-10-15 00:00:12
x5,2016-10-15 00:00:34
x6,2016-10-15 00:00:55
x7,2016-10-15 00:00:06
y7,2016-10-15 00:00:01
x8,2016-10-15 00:00:00
z3,2016-10-15 00:00:02
''' * 1000)"""

time('pd.read_csv(data); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"]); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
     'infer_datetime_format=True); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
     'date_parser=lambda x: pd.datetime.strptime(x, "%Y-%m-%d %H:%M:%S")); data.seek(0)')

プリント:

Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 03:13:28) 
[Clang 6.0 (clang-600.0.57)] on darwin
Pandas version 0.23.4
Format %m/%d/%y
0.19123052499999993
8.20691274
8.143124389
1.2384357139999977
Format %Y-%m-%d %H:%M:%S
0.5238807110000039
0.9202787830000005
0.9832778819999959
12.002349824999996

だから、ISO8601形式の日付で(%Y-%m-%d %H:%M:%S明らかにISO8601形式の日付、私はTが推測されるドロップすることができ、あなたがすべきとスペースに置き換えられ)ない指定infer_datetime_format(どちらか明らかに、より一般的なものとの違いはありません)と、独自のを渡しますパーサーはパフォーマンスを損なうだけです。一方、date_parserそれほど標準的でない日付形式では違いがあります。通常どおり、最適化する前に時間を確保してください。


1

csvファイルを読み込んでいる間、日付列が含まれています。パンダに日付列を認識させる2つの方法があります。

  1. パンダは引数によって形式を明示的に認識します date_parser=mydateparser

  2. パンダは暗黙的にagrによって形式を認識します infer_datetime_format=True

一部の日付列データ

01/01/18

01/02/18

ここでは、最初の2つのことはわかりません。月か日かもしれません。したがって、この場合は、方法1を使用する必要があります。

    mydateparser = lambda x: pd.datetime.strptime(x, "%m/%d/%y")
    df = pd.read_csv(file_name, parse_dates=['date_col_name'],
date_parser=mydateparser)

方法2:-暗黙的または自動的にフォーマットを認識する

df = pd.read_csv(file_name, parse_dates=[date_col_name],infer_datetime_format=True)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.