Quantcast
Channel: pandas - よちよちpython
Viewing all articles
Browse latest Browse all 30

【Pandas】日付の列を結合または分割する方法

$
0
0

f:id:chayarokurokuro:20210728065154j:plain

今回は↑のように、日付の列を結合したり分割したりする方法です。

【実行環境】



目次



年・月・日で3列を1列の日付型にまとめる

データフレームの列が年月日で個別なものを、1つの列で表示させたい。
サンプルのデータフレームを作ってやり方を見てみます。

☆ サンプルの生成

import numpy as np
import pandas as pd


# サンプルのデータフレーム生成
date = pd.DataFrame({
    "年":np.array(2021).repeat(10),
    "月":np.array(1).repeat(10),
    "日":np.arange(1,11),
    "何かの値":np.random.randint(0,101,10)
})

date
何かの値
020211181
120211225
220211399
320211421
420211595
520211679
620211774
720211863
820211999
9202111030

こんな風になったExcelファイルはよくありますよね。このデータフレームの左の3列を、1つの列にまとめたい。

pd.to_datetime()を使う。

pd.to_datetime()で日付に変換

# 各列を日付型に変換し、まとめて日付列として追加する
d = pd.to_datetime({
    "year":date['年'],
    "month":date['月'],
    "day":date['日']
})

print(type(d)) # 型確認

date["日付"] = d # 置換

date
<class 'pandas.core.series.Series'>
何かの値日付
0202111812021-01-01
1202112252021-01-02
2202113992021-01-03
3202114212021-01-04
4202115952021-01-05
5202116792021-01-06
6202117742021-01-07
7202118632021-01-08
8202119992021-01-09
92021110302021-01-10

pd.to_datetime()で日付型に変更したものはSeriesになっています。

注意
pd.to_datetime()の引数にある辞書のキーは*year,month,dayにしないと日付型になりません。試しにやってみます。

  • 失敗例 : 辞書のキーがyear,month,dayになっていない。
d_miss = pd.to_datetime({
    "年":date['年'],
    "月":date['月'],
    "日":date['日']
})

d_miss

出力は以下のようなエラー

ValueError: to assemble mappings requires at least that [year, month, day] be specified: [day,month,year] is missing

上手く変換できた方のデータフレームの型を見ておきます。

# 型や欠損値などの確認
date.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10 entries, 0 to 9
Data columns (total 5 columns):
 #   Column  Non-Null Count  Dtype         
---  ------  --------------  -----         
 0   年       10 non-null     int64         
 1   月       10 non-null     int64         
 2   日       10 non-null     int64         
 3   何かの値    10 non-null     int64         
 4   日付      10 non-null     datetime64[ns]
dtypes: datetime64[ns](1), int64(4)
memory usage: 528.0 bytes

日付列はdatetime型、その他の列はint型。

pd.to_datetime()の引数を辞書以外で行うこともできます。

# 日付に直したい3行を抽出
date.iloc[:,:3]
0202111
1202112
2202113
3202114
4202115
5202116
6202117
7202118
8202119
92021110
# まずはカラム名を変える
df_date = pd.DataFrame(
    date.iloc[1:, :3].values,
    columns=['year','month','day']
)

df_date
yearmonthday
0202112
1202113
2202114
3202115
4202116
5202117
6202118
7202119
82021110
# 日付に変換
pd.to_datetime(df_date)
0   2021-01-02
1   2021-01-03
2   2021-01-04
3   2021-01-05
4   2021-01-06
5   2021-01-07
6   2021-01-08
7   2021-01-09
8   2021-01-10
dtype: datetime64[ns]

結局この場合でも、カラム名year,month,dayにする必要があります。

df.rename()などでカラム名を変えてもよい。



不要な列の削除

不要な列を削除する。引数のaxis=1で列削除を指定している。これを省くとKey Error : not found in axisとエラーが出る。

date.head(3)
何かの値日付
0202111812021-01-01
1202112252021-01-02
2202113992021-01-03
# 不要な列を削除し、変数に代入
date_new = date.drop(["年","月","日"] ,axis=1)
date_new
何かの値日付
0812021-01-01
1252021-01-02
2992021-01-03
3212021-01-04
4952021-01-05
5792021-01-06
6742021-01-07
7632021-01-08
8992021-01-09
9302021-01-10

日付列が左の方が良いので、列を入れ替えます。

# 列の入れ替え
date_new = date_new.iloc[:, [1,0]]
date_new
日付何かの値
02021-01-0181
12021-01-0225
22021-01-0399
32021-01-0421
42021-01-0595
52021-01-0679
62021-01-0774
72021-01-0863
82021-01-0999
92021-01-1030

または新規にデータフレームを作成

新規に「日付」列と「何かの値」列を付けたデータフレームを作れば、列の削除はしなくて済む。

pd.DataFrame({
    '日付':d,
    '何かの値':date['何かの値']
})
日付何かの値
02021-01-0181
12021-01-0225
22021-01-0399
32021-01-0421
42021-01-0595
52021-01-0679
62021-01-0774
72021-01-0863
82021-01-0999
92021-01-1030



時刻まで入っている場合

元のデータに「年」「月」「日」「時間」「分」「秒」まで入っている場合をやってみる。やり方は同じ。

まずは列を分けたデータを生成してから。

# サンプルのデータフレーム生成
dt = pd.DataFrame({
    "年":np.array(2021).repeat(10),
    "月":np.array(1).repeat(10),
    "日":np.arange(1,11),
    '時間':np.random.randint(1,24,10),
    '分':np.random.randint(0,60,10),
    '秒':np.random.randint(0,60,10),
    "何かの値":np.random.randint(0,101,10)
})

dt
時間何かの値
020211112133695
120211211104523
22021133281730
320211417355167
4202115753397
52021162165045
620211715104874
720211816765
8202119757857
920211102159739

あとは、それぞれの列を変換。

# 各列を日付型に変換し、まとめて日付列として追加する
d_t = pd.to_datetime({
    "year":dt['年'],
    "month":dt['月'],
    "day":dt['日'],
    "hour":dt['時間'],
    "minute":dt['分'],
    "second":dt['秒']
})

print(type(d_t)) # 型確認# 表示
d_t
<class 'pandas.core.series.Series'>





0   2021-01-01 12:13:36
1   2021-01-02 11:10:45
2   2021-01-03 03:28:17
3   2021-01-04 17:35:51
4   2021-01-05 07:05:33
5   2021-01-06 02:16:50
6   2021-01-07 15:10:48
7   2021-01-08 01:06:07
8   2021-01-09 07:57:08
9   2021-01-10 21:59:07
dtype: datetime64[ns]

データフレームに変換すると…

# データフレーム化
pd.DataFrame({
    '日付':d_t,
    '何かの値':np.arange(len(d_t))
})
日付何かの値
02021-01-01 12:13:360
12021-01-02 11:10:451
22021-01-03 03:28:172
32021-01-04 17:35:513
42021-01-05 07:05:334
52021-01-06 02:16:505
62021-01-07 15:10:486
72021-01-08 01:06:077
82021-01-09 07:57:088
92021-01-10 21:59:079



またはrename()でカラム名を変換して、

# カラム名の変換
dt_df = dt.iloc[:, :-2].rename(
    columns={
        '年':'year',
        '月':'month',
        '日':'day',
        '時間':'hour',
        '分':'minute',
        '秒':'second'
    })

dt_df.head(2)
yearmonthdayhourminute
02021111213
12021121110
# カラム名を変えたデータフレームをまるごと日付型に
pd.to_datetime(dt_df)
0   2021-01-01 12:13:00
1   2021-01-02 11:10:00
2   2021-01-03 03:28:00
3   2021-01-04 17:35:00
4   2021-01-05 07:05:00
5   2021-01-06 02:16:00
6   2021-01-07 15:10:00
7   2021-01-08 01:06:00
8   2021-01-09 07:57:00
9   2021-01-10 21:59:00
dtype: datetime64[ns]
  • rename()の使い方は以下
# renameの使い方はコマンドで
?pd.DataFrame.rename

#または#help(pd.DataFrame.rename)



日付型1列を複数列に分割するには

今までとは逆に、分割するにはどうすればいいでしょうか。各属性は以下の方法で取り出せる。

# 日付型データを1つ抽出
d_t0 = d_t[0]
print(d_t0)

print('-'*20)


print('年', d_t0.year)
print('月', d_t0.month)
print('日', d_t0.day)
print('時', d_t0.hour)
print('分', d_t0.minute)
print('秒', d_t0.second)
2021-01-01 12:13:36
--------------------
年 2021
月 1
日 1
時 12
分 13
秒 36

やり方はいろいろあるとは思いますが、思い付いたのは次、

# Seriesの各データから各属性をリストで抽出しリスト化
[[i.year,i.month,i.day] for i in d_t]

[[2021, 1, 1],
 [2021, 1, 2],
 [2021, 1, 3],
 [2021, 1, 4],
 [2021, 1, 5],
 [2021, 1, 6],
 [2021, 1, 7],
 [2021, 1, 8],
 [2021, 1, 9],
 [2021, 1, 10]]
  • Seriesの各データをfor文で取り出し
  • 各属性をリスト化
  • 内包表記で全体をリスト化

上手いこと2次元のデータになった。あとはデータフレームに直すだけ。

# Seriesから年月日のリスト化
d = [[i.year,i.month,i.day] for i in d_t]
# データフレーム化
pd.DataFrame(d,columns=["年","月","日"])
    
0202111
1202112
2202113
3202114
4202115
5202116
6202117
7202118
8202119
92021110



長くなりました。以上。


Viewing all articles
Browse latest Browse all 30

Trending Articles