我有一个数据系列,其中包含一个随机日期列作为索引,一个编号值以及三列,每列指示是否激活安全机制以阻止编号值。例如:
DateTime Safe1 Safe2 Safe3 Measurement
1/8/2013 6:06 N Y N
1/8/2013 6:23 N Y N
1/8/2013 6:40 N N N 28
1/8/2013 6:57 1 N N N 31
我需要使用Pandas重新采样数据,以创建干净的半小时间隔数据,取任何存在的值的平均值。当然,这会删除三个安全字符串列。
但是,如果在整个半小时间隔内激活安全机制的任何组合,我想包括一个指示Y的列。
如何在重采样数据中显示此字符串列,表明在三个安全机制列中原始数据中存在Y而在测量中没有任何值?
基于上述所需的输出:
DateTime Safe1测量
1/8/2013 6:00 Y
2013年1月8日6:30 N 29.5
答案 0 :(得分:2)
我不认为使用重新采样功能可以做你想要的事情,因为你可以做的事情并不多。我们必须使用groupby操作来执行TimeGrouper。
首先创建数据:
import pandas as pd
index = ['1/8/2013 6:06', '1/8/2013 6:23', '1/8/2013 6:40', '1/8/2013 6:57']
data = {'Safe1' : ['N', 'N', 'N', 'N'],
'Safe2': ['Y', 'Y', 'N', 'N'],
'Safe3': ['N', 'N', 'N', 'N'],
'Measurement': [0,0,28,31]}
df = pd.DataFrame(index=index, data=data)
df.index = pd.to_datetime(df.index)
df
输出:
Measurement Safe1 Safe2 Safe3
2013-01-08 06:06:00 0 N Y N
2013-01-08 06:23:00 0 N Y N
2013-01-08 06:40:00 28 N N N
2013-01-08 06:57:00 31 N N N
然后,让我们添加一个名为 Safe 的帮助列,它将是所有Safex列的串联。如果安全列中至少有一个 Y ,我们就会知道安全机制已激活。
df['Safe'] = df['Safe1'] + df['Safe2'] + df['Safe3']
print df
输出:
Measurement Safe1 Safe2 Safe3 Safe
2013-01-08 06:06:00 0 N Y N NYN
2013-01-08 06:23:00 0 N Y N NYN
2013-01-08 06:40:00 28 N N N NNN
2013-01-08 06:57:00 31 N N N NNN
最后,我们要定义一个自定义函数,如果字符串列表中至少有一个 Y ,它将返回 Y 作为参数传递。
在我们按照30分钟的间隔对自定义函数进行分组后,该自定义函数会在安全列上传递:
def func(x):
x = ''.join(x.values)
return 'Y' if 'Y' in x else 'N'
df.groupby(pd.TimeGrouper(freq='30Min')).agg({'Measurement': 'mean', 'Safe': func })
输出:
Safe Measurement
2013-01-08 06:00:00 Y 0.0
2013-01-08 06:30:00 N 29.5
答案 1 :(得分:2)
这是使用pandas内置重采样功能的答案。
首先将3个安全值合并为一个列:
(3,4)
将3个字母的字符串转换为0-1变量:
df['Safe'] = df.Safe1 + df.Safe2 + df.Safe3
为“保险箱”栏写一个自定义重新取样功能:
df.Safe = df.Safe.apply(lambda x: 1 if 'Y' in x else 0)
最后,重新采样:
def f(x):
if sum(x) > 0: return 'Y'
else: return 'N'
输出:
df.resample('30T').Safe.agg({'Safe': f}).join(df.resample('30T').Measurement.mean())
答案 2 :(得分:0)
我手动重新采样日期(如果四舍五入,这很容易)。...
这是一个例子
from random import shuffle
from datetime import datetime, timedelta
from itertools import zip_longest
from random import randint, randrange, seed
from tabulate import tabulate
import pandas as pd
def df_to_md(df):
print(tabulate(df, tablefmt="pipe",headers="keys"))
seed(42)
people=['tom','dick','harry']
avg_score=[90,50,10]
date_times=[n for n in pd.date_range(datetime.now()-timedelta(days=2),datetime.now(),freq='5 min').values]
scale=1+int(len(date_times)/len(people))
score =[randint(i,100)*i/10000 for i in avg_score*scale]
df=pd.DataFrame.from_records(list(zip(date_times,people*scale,score)),columns=['When','Who','Status'])
# Create 3 records tom should score 90%, dick 50% and poor harry only 10%
# Tom should score well
df_to_md(df[df.Who=='tom'].head())
表格采用Markdown格式-只是为了方便我剪切和粘贴。...
| | When | Who | Status |
|---:|:---------------------------|:------|---------:|
| 0 | 2019-06-18 14:07:17.457124 | tom | 0.9 |
| 3 | 2019-06-18 14:22:17.457124 | tom | 0.846 |
| 6 | 2019-06-18 14:37:17.457124 | tom | 0.828 |
| 9 | 2019-06-18 14:52:17.457124 | tom | 0.9 |
| 12 | 2019-06-18 15:07:17.457124 | tom | 0.819 |
df_to_md(df[df.Who=='harry'].head())
| | When | Who | Status |
|---:|:---------------------------|:------|---------:|
| 2 | 2019-06-18 14:17:17.457124 | harry | 0.013 |
| 5 | 2019-06-18 14:32:17.457124 | harry | 0.038 |
| 8 | 2019-06-18 14:47:17.457124 | harry | 0.023 |
| 11 | 2019-06-18 15:02:17.457124 | harry | 0.079 |
| 14 | 2019-06-18 15:17:17.457124 | harry | 0.064 |
def round_to_hour(t):
# Rounds to nearest hour by adding a timedelta hour if minute >= 30
return (t.replace(second=0, microsecond=0, minute=0, hour=t.hour)
+timedelta(hours=t.minute//30))
并使用此方法生成新列。
df['WhenRounded']=df.When.apply(lambda x: round_to_hour(x))
df_to_md(df[df.Who=='tom'].head())
这应该是汤姆的数据-显示原始和四舍五入。
| | When | Who | Status | WhenRounded |
|---:|:---------------------------|:------|---------:|:--------------------|
| 0 | 2019-06-18 14:07:17.457124 | tom | 0.9 | 2019-06-18 14:00:00 |
| 3 | 2019-06-18 14:22:17.457124 | tom | 0.846 | 2019-06-18 14:00:00 |
| 6 | 2019-06-18 14:37:17.457124 | tom | 0.828 | 2019-06-18 15:00:00 |
| 9 | 2019-06-18 14:52:17.457124 | tom | 0.9 | 2019-06-18 15:00:00 |
| 12 | 2019-06-18 15:07:17.457124 | tom | 0.819 | 2019-06-18 15:00:00 |
按四舍五入日期和Person(日期时间和Str)对象分组)-在这种情况下,我们需要平均值值,但也可以使用其他值。
df_resampled=df.groupby(by=['WhenRounded','Who'], axis=0).agg({'Status':'mean'}).reset_index()
# Output in Markdown format
df_to_md(df_resampled[df_resampled.Who=='tom'].head())
| | WhenRounded | Who | Status |
|---:|:--------------------|:------|---------:|
| 2 | 2019-06-18 14:00:00 | tom | 0.873 |
| 5 | 2019-06-18 15:00:00 | tom | 0.83925 |
| 8 | 2019-06-18 16:00:00 | tom | 0.86175 |
| 11 | 2019-06-18 17:00:00 | tom | 0.84375 |
| 14 | 2019-06-18 18:00:00 | tom | 0.8505 |
让我们检查@ 14:00的tom平均值
print("Check tom 14:00 .86850 ... {:6.5f}".format((.900+.846+.828+.900)/4))
Check tom 14:00 .86850 ... 0.86850
希望有帮助