如何在 pandas 中为一天中的所有小时分配固定值
How to assign a fix value to all hour of a day in pandas
我有一个包含两列的半小时数据框。我想花一天的所有时间,然后做一些计算 returns 一个数字并将其分配给当天的所有半小时。下面是一个示例代码:
dates = pd.date_range("2003-01-01 08:30:00","2003-01-05",freq="30min")
data = np.transpose(np.array([np.random.rand(dates.shape[0]),np.random.rand(dates.shape[0])*100]))
data[0:50,0]=np.nan # my actual dataframe includes nan
df = pd.DataFrame(data = data,index =dates,columns=["DATA1","DATA2"])
print(df)
DATA1 DATA2
2003-01-01 08:30:00 NaN 79.990866
2003-01-01 09:00:00 NaN 5.461791
2003-01-01 09:30:00 NaN 68.892447
2003-01-01 10:00:00 NaN 44.823338
2003-01-01 10:30:00 NaN 57.860309
... ... ...
2003-01-04 22:00:00 0.394574 31.943657
2003-01-04 22:30:00 0.140950 78.275981
然后我想应用以下函数,其中returns一个数字:
def my_f(data1,data2):
y = data1[data2>20]
return np.median(y)
此函数根据条件(DATA2>20)选择DATA1中的所有数据,然后取所有这些数据的中值。
我如何创建第三列(比如结果)并为当天所有半小时数据分配回这个固定数字 (y)?
我猜我应该使用这样的东西:
daily_tmp = df.resample('D').apply(my_f)
df['results'] = b.reindex(df.index,method='ffill')
如果这种方法是正确的,我如何将带有两个参数的 my_f 传递给 resample.apply()?
或者有没有其他方法可以完成类似的任务?
我的解决方案假设您有一个相当小的数据集。如果不是这样,请告诉我。
我会将你的目标分解如下:
(1) 按天分组数据
(2) 每天计算一些复杂的函数
(3) 将结果值赋给半小时。
# specify the day for each datapoint
df['day'] = df.index.map(lambda x: x.strftime('%Y-%m-%d'))
# compute a complicated function for each day and store the result
mapping = {}
for day, data_for_the_day in df.groupby(by='day'):
# assign to mapping[day] the result of a complicated function
mapping[day] = np.mean(data_for_the_day[data_for_the_day['Data2'] > 20]['Data1'])
# assign the values to half-hours
df['result'] = df.index.map(lambda x: mapping.get(x.strftime('%Y-%m-%d'), np.nan) if x.strftime('%M')=='30' else np.nan)
这不是最巧妙的解决方案,但它简单明了、易于理解,并且适用于小型数据集。
这是一个快速的方法。
首先,导入库:
import time
import pandas as pd
import numpy as np
import datetime as dt
二、实现代码:
%%time
dates = pd.date_range("2003-01-01 08:30:00","2003-01-05",freq="30min")
data = np.transpose(np.array([np.random.rand(dates.shape[0]),np.random.rand(dates.shape[0])*100]))
data[0:50,0]=np.nan # my actual dataframe includes nan
df = pd.DataFrame(data = data,index =dates,columns=["DATA1","DATA2"])
#### Create an unique marker per hour
df['Date'] = df.index
df['Date'] = df['Date'].dt.strftime(date_format='%Y-%m-%d %H')
#### Then Stipulate some conditions
_condition_1 = df.Date == df.Date.shift(-1) # if full hour
_condition_2 = df.DATA2 > 20 # yours
_condition_3 = df.Date == df.Date.shift(1) # if half an hour
#### Now, report median where condition 1 and 2 are fullfilled
df['result'] = np.where(_condition_1 & _condition_2,(df.DATA1+df.DATA1.shift(-1)/2),0)
#### Fill the hours with median
df['result'] = np.where(_condition_3,df.result.shift(1),df.result)
#### Drop useless column
df = df.drop(['Date'],axis=1)
df[df.DATA2>20].tail(20)
第三:输出
output
我有一个包含两列的半小时数据框。我想花一天的所有时间,然后做一些计算 returns 一个数字并将其分配给当天的所有半小时。下面是一个示例代码:
dates = pd.date_range("2003-01-01 08:30:00","2003-01-05",freq="30min")
data = np.transpose(np.array([np.random.rand(dates.shape[0]),np.random.rand(dates.shape[0])*100]))
data[0:50,0]=np.nan # my actual dataframe includes nan
df = pd.DataFrame(data = data,index =dates,columns=["DATA1","DATA2"])
print(df)
DATA1 DATA2
2003-01-01 08:30:00 NaN 79.990866
2003-01-01 09:00:00 NaN 5.461791
2003-01-01 09:30:00 NaN 68.892447
2003-01-01 10:00:00 NaN 44.823338
2003-01-01 10:30:00 NaN 57.860309
... ... ...
2003-01-04 22:00:00 0.394574 31.943657
2003-01-04 22:30:00 0.140950 78.275981
然后我想应用以下函数,其中returns一个数字:
def my_f(data1,data2):
y = data1[data2>20]
return np.median(y)
此函数根据条件(DATA2>20)选择DATA1中的所有数据,然后取所有这些数据的中值。 我如何创建第三列(比如结果)并为当天所有半小时数据分配回这个固定数字 (y)?
我猜我应该使用这样的东西:
daily_tmp = df.resample('D').apply(my_f)
df['results'] = b.reindex(df.index,method='ffill')
如果这种方法是正确的,我如何将带有两个参数的 my_f 传递给 resample.apply()? 或者有没有其他方法可以完成类似的任务?
我的解决方案假设您有一个相当小的数据集。如果不是这样,请告诉我。
我会将你的目标分解如下: (1) 按天分组数据 (2) 每天计算一些复杂的函数 (3) 将结果值赋给半小时。
# specify the day for each datapoint
df['day'] = df.index.map(lambda x: x.strftime('%Y-%m-%d'))
# compute a complicated function for each day and store the result
mapping = {}
for day, data_for_the_day in df.groupby(by='day'):
# assign to mapping[day] the result of a complicated function
mapping[day] = np.mean(data_for_the_day[data_for_the_day['Data2'] > 20]['Data1'])
# assign the values to half-hours
df['result'] = df.index.map(lambda x: mapping.get(x.strftime('%Y-%m-%d'), np.nan) if x.strftime('%M')=='30' else np.nan)
这不是最巧妙的解决方案,但它简单明了、易于理解,并且适用于小型数据集。
这是一个快速的方法。
首先,导入库:
import time
import pandas as pd
import numpy as np
import datetime as dt
二、实现代码:
%%time
dates = pd.date_range("2003-01-01 08:30:00","2003-01-05",freq="30min")
data = np.transpose(np.array([np.random.rand(dates.shape[0]),np.random.rand(dates.shape[0])*100]))
data[0:50,0]=np.nan # my actual dataframe includes nan
df = pd.DataFrame(data = data,index =dates,columns=["DATA1","DATA2"])
#### Create an unique marker per hour
df['Date'] = df.index
df['Date'] = df['Date'].dt.strftime(date_format='%Y-%m-%d %H')
#### Then Stipulate some conditions
_condition_1 = df.Date == df.Date.shift(-1) # if full hour
_condition_2 = df.DATA2 > 20 # yours
_condition_3 = df.Date == df.Date.shift(1) # if half an hour
#### Now, report median where condition 1 and 2 are fullfilled
df['result'] = np.where(_condition_1 & _condition_2,(df.DATA1+df.DATA1.shift(-1)/2),0)
#### Fill the hours with median
df['result'] = np.where(_condition_3,df.result.shift(1),df.result)
#### Drop useless column
df = df.drop(['Date'],axis=1)
df[df.DATA2>20].tail(20)
第三:输出
output