如何解决大熊猫:对多索引数据框重新采样
我有一个带有多个索引的数据框:“主题”和“日期时间”。 每行对应一个主题和一个日期时间,数据框的各列对应各种度量。
每个主题的天数范围不同,并且给定主题的天数可能会丢失(请参见示例)。而且,一个对象在一天中可以有一个或多个值。
我想对数据框重新采样,以便:
- 每个主题每天只有一行(我不在乎一天中的时间)
- 每个列的值都是当天的最后一个非NaN(如果当天没有值,则为NaN)
- 在任何列上都没有值的日子不会被创建或保留。
例如,以下数据框示例:
a b
subject datetime
patient1 2018-01-01 00:00:00 2.0 high
2018-01-01 01:00:00 NaN medium
2018-01-01 02:00:00 6.0 NaN
2018-01-01 03:00:00 NaN NaN
2018-01-02 00:00:00 4.3 low
patient2 2018-01-01 00:00:00 NaN medium
2018-01-01 02:00:00 NaN NaN
2018-01-01 03:00:00 5.0 NaN
2018-01-03 00:00:00 9.0 NaN
2018-01-04 02:00:00 NaN NaN
应返回:
a b
subject datetime
patient1 2018-01-01 00:00:00 6.0 medium
2018-01-02 00:00:00 4.3 low
patient2 2018-01-01 00:00:00 5.0 medium
2018-01-03 00:00:00 9.0 NaN
我花了太多时间试图通过使用'pad'选项进行重采样来获得此结果,但是我总是会出错,或者无法获得想要的结果。有人可以帮忙吗?
注意:这是创建示例数据框的代码:
import pandas as pd
import numpy as np
index = pd.MultiIndex.from_product([['patient1','patient2'],pd.date_range('20180101',periods=4,freq='h')])
df = pd.DataFrame({'a': [2,np.nan,6,5],'b': ['high','medium','low',np.nan]},index=index)
df.index.names = ['subject','datetime']
df = df.drop(df.index[5])
df.at[('patient2','2018-01-03 00:00:00'),'a'] = 9
df.at[('patient2','2018-01-04 02:00:00'),'a'] = None
df.at[('patient1','2018-01-02 00:00:00'),'a'] = 4.3
df.at[('patient1','b'] = 'low'
df = df.sort_index(level=['subject','datetime'])
解决方法
让我们以每天的频率floor
datetime
,然后groupby
subject
+下限时间戳记的数据帧和agg
使用last
,最后drop
行全部包含NaN's
:
i = pd.to_datetime(df.index.get_level_values(1)).floor('d')
df1 = df.groupby(['subject',i]).agg('last').dropna(how='all')
a b
subject datetime
patient1 2018-01-01 6.0 medium
2018-01-02 4.3 low
patient2 2018-01-01 5.0 medium
2018-01-03 9.0 NaN
,
# drop a et b we don't need them when they ='re both na
df = df.reset_index().dropna(subset=["a","b"],how="all")
#add a day columns we need it to keep last value
df["dt_day"] = df["datetime"].dt.date
#d1 result dataframe which we add a et b
d1 = df.copy().drop_duplicates(subset=["subject","dt_day"]).loc[:,["subject","datetime"]].reset_index(drop=True)
#add a et b to ou dataframe result
for col in ["a","b"]:
d1.loc[:,col] = (df.copy().
dropna(subset=[col]).drop_duplicates(subset=["subject","dt_day"],keep="last")[col]
.reset_index(drop=True))
Wall time: 24 ms
@Shubham Sharma code => Wall time: 2.94 ms
subject datetime a b
0 patient1 2018-01-01 6.0 medium
1 patient1 2018-01-02 4.3 low
2 patient2 2018-01-01 5.0 medium
3 patient2 2018-01-03 9.0 NaN
感谢您的提问:)
,这应该可以完成工作:
def day_agg(series_):
try:
return series_.dropna().iloc[-1]
except IndexError:
return float("nan")
df = df.reset_index().sort_values("datetime")
df.groupby([df["subject"],df.datetime.map(lambda x:datetime(year=x.year,month=x.month,day=x.day))])\
.agg({"a":day_agg,"b":day_agg})\
.dropna(how="all")
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。