pandas 多个数据框列到单个日期时间索引
pandas multiple dataframe columns to single datetime index
我有一个 pandas 数据框(无索引),其排列看起来像这样笨拙,但大约有 60,000 行长:
YYYYMMDD, HH, DATA
20110101, 1, 220
20110101, 2, 220
20110101, 3, 220
20110101, 4, 230
20110101, 5, 230
20110101, 6, 220
20110101, 7, 240
20110101, 8, 230
20110101, 9, 230
20110101, 10, 230
20110101, 11, 240
20110101, 12, 230
20110101, 13, 240
20110101, 14, 240
20110101, 15, 260
20110101, 16, 270
20110101, 17, 280
20110101, 18, 300
20110101, 19, 300
20110101, 20, 320
20110101, 21, 310
20110101, 22, 310
20110101, 23, 310
20110101, 24, 300
20110102, 1, 290
20110102, 2, 270
第一列是 YYYYMMDD,第二列是小时。我想用这些做一个pd.datetimeindex,但是有一些问题。
与 HH 标题相反,HH 数据没有前导零,date-time 例如 '20110101, 24' 实际上应该读作 '20110102, 00' 以便 pd.to_datetime 工作,即你不应该有一个小时是 24,如果它是 24,它应该是 00 并且日期递增。
我目前已经走到这一步:
f = lambda x: pd.to_datetime(x, format='%Y%m%d %H', exact=False)
df = pd.read_csv(path)
dates = df.YYYYMMDD.apply(lambda x: str(x)+' ') \
+ df.HH.apply(lambda x: '0'+str(x) if len(str(x))==1 else str(x))
dates.apply(f)
第三行创建了一个系列,将两列组合在一起并在必要时添加前导零,但我无法优雅地处理边缘情况,即 24 小时需要更改为 00,并且日期需要递增一。它需要在月末和年末工作(在“20111231 24”的情况下,日期、月份和年份都需要递增)。
尝试执行 dates.apply(f) 给出了预期的错误,即 24 是意外的:
ValueError: time data '20110101 24' doesn't match format specified
有人知道优雅地做到这一点的方法吗?我想要一个 pandas._libs.tslib.Timestamp 类型的列,我可以轻松地将其转换为索引。
非常感谢。使用Python 3.6,你可以在这里找到源数据:https://cdn.knmi.nl/knmi/map/page/klimatologie/gegevens/uurgegevens/uurgeg_380_2011-2020.zip (from this website www.knmi.nl)
编辑:我必须自己添加前导 0,因为我无法让 %-H 作为参数工作。显然它不适用于所有后端,得到与这个好人相同的错误
(如果您使用的是源数据,您可能会发现这很有用):
path = '/uurgeg_380_2011-2020.txt'
header_row = pd.read_csv(path, sep=",", skiprows=31, nrows=0).columns.values
header_row = np.array([x.replace(' ','').replace('#','') for x in header_row])
f = lambda x: pd.to_datetime(x, format='%Y%m%d %H', exact=False)
df = pd.read_csv(path, skiprows=32, names=header_row)
dates = df.YYYYMMDD.apply(lambda x: str(x)+' ') \
+ df.HH.apply(lambda x: '0'+str(x) if len(str(x))==1 else str(x))
dates.apply(f)
您可以分几步完成此操作:
- 将
YYYYMMDD
更改为日期时间(只是日期)
- 在
24
条目中添加一天(使用 Timedelta
)
- 将
24
更改为零
- 零填充
HH
列(作为字符串类型,使用 zfill
)
- 创建日期时间列:
像这样:
df['YYYYMMDD'] = pd.to_datetime(df.YYYYMMDD, format='%Y%m%d')
df.loc[df.HH == 24, 'YYYYMMDD'] += pd.Timedelta(days=1)
df.loc[df.HH == 24, 'HH'] = 0
df['HH'] = df.HH.astype(str).str.zfill(2)
df.index = pd.to_datetime(df['YYYYMMDD'].astype(str) + ' ' + df['HH'],
format='%Y-%m-%d %H')
然后可以看看新建的索引:
>>> df.index
DatetimeIndex(['2011-01-01 01:00:00', '2011-01-01 02:00:00',
'2011-01-01 03:00:00', '2011-01-01 04:00:00',
'2011-01-01 05:00:00', '2011-01-01 06:00:00',
'2011-01-01 07:00:00', '2011-01-01 08:00:00',
'2011-01-01 09:00:00', '2011-01-01 10:00:00',
'2011-01-01 11:00:00', '2011-01-01 12:00:00',
'2011-01-01 13:00:00', '2011-01-01 14:00:00',
'2011-01-01 15:00:00', '2011-01-01 16:00:00',
'2011-01-01 17:00:00', '2011-01-01 18:00:00',
'2011-01-01 19:00:00', '2011-01-01 20:00:00',
'2011-01-01 21:00:00', '2011-01-01 22:00:00',
'2011-01-01 23:00:00', '2011-01-02 00:00:00',
'2011-01-02 01:00:00', '2011-01-02 02:00:00'],
dtype='datetime64[ns]', freq=None)
我有一个 pandas 数据框(无索引),其排列看起来像这样笨拙,但大约有 60,000 行长:
YYYYMMDD, HH, DATA
20110101, 1, 220
20110101, 2, 220
20110101, 3, 220
20110101, 4, 230
20110101, 5, 230
20110101, 6, 220
20110101, 7, 240
20110101, 8, 230
20110101, 9, 230
20110101, 10, 230
20110101, 11, 240
20110101, 12, 230
20110101, 13, 240
20110101, 14, 240
20110101, 15, 260
20110101, 16, 270
20110101, 17, 280
20110101, 18, 300
20110101, 19, 300
20110101, 20, 320
20110101, 21, 310
20110101, 22, 310
20110101, 23, 310
20110101, 24, 300
20110102, 1, 290
20110102, 2, 270
第一列是 YYYYMMDD,第二列是小时。我想用这些做一个pd.datetimeindex,但是有一些问题。
与 HH 标题相反,HH 数据没有前导零,date-time 例如 '20110101, 24' 实际上应该读作 '20110102, 00' 以便 pd.to_datetime 工作,即你不应该有一个小时是 24,如果它是 24,它应该是 00 并且日期递增。
我目前已经走到这一步:
f = lambda x: pd.to_datetime(x, format='%Y%m%d %H', exact=False)
df = pd.read_csv(path)
dates = df.YYYYMMDD.apply(lambda x: str(x)+' ') \
+ df.HH.apply(lambda x: '0'+str(x) if len(str(x))==1 else str(x))
dates.apply(f)
第三行创建了一个系列,将两列组合在一起并在必要时添加前导零,但我无法优雅地处理边缘情况,即 24 小时需要更改为 00,并且日期需要递增一。它需要在月末和年末工作(在“20111231 24”的情况下,日期、月份和年份都需要递增)。
尝试执行 dates.apply(f) 给出了预期的错误,即 24 是意外的:
ValueError: time data '20110101 24' doesn't match format specified
有人知道优雅地做到这一点的方法吗?我想要一个 pandas._libs.tslib.Timestamp 类型的列,我可以轻松地将其转换为索引。
非常感谢。使用Python 3.6,你可以在这里找到源数据:https://cdn.knmi.nl/knmi/map/page/klimatologie/gegevens/uurgegevens/uurgeg_380_2011-2020.zip (from this website www.knmi.nl)
编辑:我必须自己添加前导 0,因为我无法让 %-H 作为参数工作。显然它不适用于所有后端,得到与这个好人相同的错误
(如果您使用的是源数据,您可能会发现这很有用):
path = '/uurgeg_380_2011-2020.txt'
header_row = pd.read_csv(path, sep=",", skiprows=31, nrows=0).columns.values
header_row = np.array([x.replace(' ','').replace('#','') for x in header_row])
f = lambda x: pd.to_datetime(x, format='%Y%m%d %H', exact=False)
df = pd.read_csv(path, skiprows=32, names=header_row)
dates = df.YYYYMMDD.apply(lambda x: str(x)+' ') \
+ df.HH.apply(lambda x: '0'+str(x) if len(str(x))==1 else str(x))
dates.apply(f)
您可以分几步完成此操作:
- 将
YYYYMMDD
更改为日期时间(只是日期) - 在
24
条目中添加一天(使用Timedelta
) - 将
24
更改为零 - 零填充
HH
列(作为字符串类型,使用zfill
) - 创建日期时间列:
像这样:
df['YYYYMMDD'] = pd.to_datetime(df.YYYYMMDD, format='%Y%m%d')
df.loc[df.HH == 24, 'YYYYMMDD'] += pd.Timedelta(days=1)
df.loc[df.HH == 24, 'HH'] = 0
df['HH'] = df.HH.astype(str).str.zfill(2)
df.index = pd.to_datetime(df['YYYYMMDD'].astype(str) + ' ' + df['HH'],
format='%Y-%m-%d %H')
然后可以看看新建的索引:
>>> df.index
DatetimeIndex(['2011-01-01 01:00:00', '2011-01-01 02:00:00',
'2011-01-01 03:00:00', '2011-01-01 04:00:00',
'2011-01-01 05:00:00', '2011-01-01 06:00:00',
'2011-01-01 07:00:00', '2011-01-01 08:00:00',
'2011-01-01 09:00:00', '2011-01-01 10:00:00',
'2011-01-01 11:00:00', '2011-01-01 12:00:00',
'2011-01-01 13:00:00', '2011-01-01 14:00:00',
'2011-01-01 15:00:00', '2011-01-01 16:00:00',
'2011-01-01 17:00:00', '2011-01-01 18:00:00',
'2011-01-01 19:00:00', '2011-01-01 20:00:00',
'2011-01-01 21:00:00', '2011-01-01 22:00:00',
'2011-01-01 23:00:00', '2011-01-02 00:00:00',
'2011-01-02 01:00:00', '2011-01-02 02:00:00'],
dtype='datetime64[ns]', freq=None)