我有一个像这样的CSV文件:
id,timestamp
1,2015-03-02
2,2015-03-03
然后我加载到这样的DataFrame中:
df = pd.read_csv('file.csv', index_col=['id'], parse_dates=['timestamp'])
然后我按ID分组,选择时间戳列,并应用函数返回时间戳 - 天
df.groupby(level='id')['timestamp'].apply(lambda x: x - pd.Timedelta('1 days'))
结果:
id
1 2015-03-01
2 2015-03-02
Name: timestamp, dtype: datetime64[ns]
但是,当我将unique()应用于groupby对象时,时间戳会更改为意外格式。
df.groupby(level='id')['timestamp'].unique().apply(lambda x: x - pd.Timedelta('1 days'))
id
1 [2015-03-02T00:00:00.000000000]
2 [2015-03-03T00:00:00.000000000]
Name: timestamp, dtype: object
如何维护日期格式?
答案 0 :(得分:2)
unique
返回唯一值的序列。这就是
df.groupby(level='id')['timestamp'].unique()
是一系列列表。
相反,要删除重复项,请使用drop_duplicates
:
result = df.reset_index().drop_duplicates(subset=['id', 'timestamp']).set_index('id')
由于drop_duplicates
要求子集成为列列表,因此上面使用reset_index
将id
索引级别移至列,并使用set_index
移动删除重复项后返回索引。
尽可能避免使用apply
。当传递自定义Python函数时,apply
在普通的Python循环中调用该函数 - 因此它比矢量化操作慢。
如果您可以使用矢量化操作执行计算,则代码将运行得更快。
在这种情况下,可以更快地从整个列中一次减去1天(无论是组还是重复):
df['timestamp'] -= pd.Timedelta(days=1)
这种情况可能较慢的一种情况是,如果DataFrame很大但是由
只有一个(或几个)('id', 'timestamp')
组。但总的来说,应用一个
对整列的矢量化操作将比多个函数更快
呼叫应用于较小的组。
所以,例如,
import pandas as pd
import numpy as np
Timestamp = pd.Timestamp
df = pd.DataFrame({'timestamp': [Timestamp('2015-03-02 00:00:00'), Timestamp('2015-03-02 00:00:00'), Timestamp('2015-03-03 00:00:00'), Timestamp('2015-03-03 00:00:00')]}, index=pd.Index([1, 1, 1, 2], name='id'),)
# timestamp
# id
# 1 2015-03-02
# 1 2015-03-02
# 1 2015-03-03
# 2 2015-03-03
df['timestamp'] -= pd.Timedelta(days=1)
result = df.reset_index().drop_duplicates(subset=['id', 'timestamp']).set_index('id')
print(result)
# timestamp
# id
# 1 2015-03-01
# 1 2015-03-02
# 2 2015-03-02
答案 1 :(得分:0)
groupby返回数组,这就是为什么你看到它们显示的原因。如果你想要一个具有时间戳的系列,你需要使用类似下面的apply方法来获取这些值。
grouped = df.groupby(level='id')['timestamp'].unique().apply(lambda x: x - pd.Timedelta('1 days'))
grouped.apply(lambda x: x[0])
>
id
1 2015-03-01
2 2015-03-02
Name: timestamp, dtype: datetime64[ns]
答案 2 :(得分:0)
格式正在变为列表,因为您要求的是唯一值(可能有多个值)。比方说,你可以只返回第一个:
df.groupby(level='id')['timestamp'].unique().apply(lambda x: x[0] - pd.Timedelta('1 days'))
PS。我的猜测是@ unutbu的解决方案对你来说会更好。