今日、データファイル(たとえば)からデータを読み取り中にpandasが値のタイプを認識できるという事実に前向きに驚きました。
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 date-objectsではなく)文字列として認識されました。 pandasを認識された日付に「学習」する方法はありますか?
読み取り時にparse_dates=True
またはparse_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)
このようにして、複数の列を単一のdatetime列に結合することもできます。これにより、「date」列と「time」列が単一の「datetime」列にマージされます。
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)
strptime
およびstrftime
のディレクティブ(つまり、さまざまな形式で使用される文字) このページ を見つけることができます。
@Rutgerが応答してからpandasインターフェイスが変更された可能性がありますが、使用しているバージョン(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)
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’
日付のデフォルトの検出はうまく機能しますが、北米の日付形式に偏っているようです。他の場所に住んでいる場合、結果に時々気付かれるかもしれません。私が覚えている限りでは、1/6/2000は私が住んでいる6月1日とは対照的に、米国では1月6日を意味します。 2000年6月23日のような日付が使用されている場合、それらを振り回すのに十分賢いです。ただし、日付のYYYYMMDDバリエーションを使用する方が安全です。ここでpandas開発者に謝罪しますが、最近現地の日付でテストしていません。
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つの列を1つのdatetime列にマージすると、列が個別に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)
はい-pandas.read_csv
に従って ドキュメント :
注: iso8601-formatted の日付には高速パスが存在します。
したがって、csvにdatetime
という名前の列があり、日付がたとえば2013-01-01T01:01
のように見える場合、これを実行するとpandas(v0.19.2にいます)が自動的に日付と時刻を取得します。
df = pd.read_csv('test.csv', parse_dates=['datetime'])
parse_dates
を明示的に渡す必要があることに注意してください。
で検証する:
df.dtypes
列のデータ型がdatetime64[ns]
であることがわかります。
pandas.to_datetime()
のドキュメントで推奨されているように pandas.read_csv()
を使用できます。
列またはインデックスに解析できない日付が含まれる場合、列またはインデックス全体が変更されずにオブジェクトデータ型として返されます。非標準の日時の解析には、
pd.to_datetime
の後に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
パフォーマンスが重要な場合は、時間を確認してください。
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 ドロップ可能 でスペースに置き換えられると思われます)not指定infer_datetime_format
(これは明らかに一般的なものと違いはありません)、パフォーマンスを損なうだけで独自のパーサーを渡します。一方、date_parser
は、それほど標準的でない日付形式とは違います。通常どおり、最適化する前に時間を確認してください。