我记录一个设备,每15分钟读取3个值(W1
,W2
,W3
)。它们可以重复。
我需要找出每小时在该间隔内读取的12个值中最大的3个值是什么。我对它们何时发生不感兴趣,只对它们的值感兴趣。
目前,我的算法还远远不够高效和快速:
我想去掉这个循环,使用原生的pandas/numpy方法。可能吗?
编辑:在这篇文章的末尾提出了一个可行的解决方案
以下是代码:
from datetime import *
import pandas as pd
import numpy as np
df = pd.DataFrame()
date_ref = datetime(2017,12,8,0,0,0)
days = pd.date_range(date_ref, date_ref + timedelta(0.11), freq='15min')
np.random.seed(seed=1111)
data1 = np.random.randint(1, high=100, size=len(days))
data2 = data1 - np.random.randint(3, high=13, size=len(days))
data3 = data2 - np.random.randint(3, high=13, size=len(days))
df = pd.DataFrame({'TIME': days, 'W1': data1, 'W2': data2, 'W3': data3 })
df = df.set_index('TIME')
print("Original data")
print("-------------")
print(df)
print("**********************************************")
# groupby
grouped = df.groupby(pd.Grouper(freq='1H'))
print("Grouped data")
print("------------")
print list(grouped)
print("**********************************************")
print("3 largest values")
print("----------------")
for dtime, group in grouped:
w = list(group["W1"])
w2 = list(group["W2"])
w3 = list(group["W3"])
w.extend(w2)
w.extend(w3)
w = sorted(w)
max1 = w[-1]
max2 = w[-2]
max3 = w[-3]
print(dtime, max1, max2, max3)
回报:
Original data
-------------
W1 W2 W3
TIME
2017-12-08 00:00:00 78 67 57
2017-12-08 00:15:00 73 64 59
2017-12-08 00:30:00 55 50 47
2017-12-08 00:45:00 67 58 51
2017-12-08 01:00:00 62 51 40
2017-12-08 01:15:00 52 40 32
2017-12-08 01:30:00 70 64 56
2017-12-08 01:45:00 74 67 63
2017-12-08 02:00:00 72 61 56
2017-12-08 02:15:00 70 58 55
2017-12-08 02:30:00 61 49 39
**********************************************
Grouped data
------------
[(Timestamp('2017-12-08 00:00:00', freq='H'), W1 W2 W3
TIME
2017-12-08 00:00:00 78 67 57
2017-12-08 00:15:00 73 64 59
2017-12-08 00:30:00 55 50 47
2017-12-08 00:45:00 67 58 51), (Timestamp('2017-12-08 01:00:00', freq='H'), W1 W2 W3
TIME
2017-12-08 01:00:00 62 51 40
2017-12-08 01:15:00 52 40 32
2017-12-08 01:30:00 70 64 56
2017-12-08 01:45:00 74 67 63), (Timestamp('2017-12-08 02:00:00', freq='H'), W1 W2 W3
TIME
2017-12-08 02:00:00 72 61 56
2017-12-08 02:15:00 70 58 55
2017-12-08 02:30:00 61 49 39)]
**********************************************
3 largest values
----------------
(Timestamp('2017-12-08 00:00:00', freq='H'), 78, 73, 67)
(Timestamp('2017-12-08 01:00:00', freq='H'), 74, 70, 67)
(Timestamp('2017-12-08 02:00:00', freq='H'), 72, 70, 61)
解决方案
我在代码中实现这个解决方案时遇到了一些困难,所以我将最终版本留给后代。也许它对某些人有用。
即使@jezrael的解决方案在我的演示中起作用,但在我的最终版本中却不起作用。它抱怨时间戳不能被否定。调试pandas组非常困难,所以我使用了@GeorgeLPerkins。它(对我来说)更容易理解。
最大的问题是分组。apply()
返回一系列列表。
从每个列表中提取每个元素是使用<代码> STR 进行的:正如名称所示,我认为它只涉及字符串,而没有考虑它。
现在每个直接循环都被避免了,结果gdf
是一个数据帧,只需一次写入操作就可以保存到数据库中。
我是熊猫的新手,唉,我想这是可以高度优化的。
from datetime import *
import pandas as pd
import numpy as np
df = pd.DataFrame()
date_ref = datetime(2017,12,8,0,0,0)
days = pd.date_range(date_ref, date_ref + timedelta(0.11), freq='15min')
np.random.seed(seed=1111)
data1 = np.random.randint(50, high=80, size=len(days))
data2 = data1 - np.random.randint(3, high=13, size=len(days))
data3 = data2 - np.random.randint(3, high=13, size=len(days))
df = pd.DataFrame({'TIME': days, 'W1': data1, 'W2': data2, 'W3': data3 })
df = df.set_index('TIME')
#print("Original data")
#print("-------------")
#print(df)
#print("**********************************************")
# groupby
grouped = df.groupby(pd.Grouper(freq='1H'))
print("Grouped data")
print("------------")
print list(grouped)
print("**********************************************")
print("3 largest values")
print("----------------")
def operation(x):
combinedcoltop3 = []
combinedcoltop3.extend(list(x.nlargest(3, "W1")["W1"])) # reads the 3 largest W1 and return W1 only
combinedcoltop3.extend(list(x.nlargest(3, "W2")["W2"]))
combinedcoltop3.extend(list(x.nlargest(3, "W3")["W3"]))
combinedcoltop3.sort(reverse=True)
return combinedcoltop3[:3] # returns a list!
df1 = grouped.apply(operation)
gdf = pd.DataFrame()
gdf["W1"] = df1.str[0] # reads each element of the list for each row of df1
gdf["W2"] = df1.str[1]
gdf["W3"] = df1.str[2]
print(gdf)
# now gdf can be saved with a single write into the database
我发现更简单的是:
combinedcoltop3 = []
for col in df.columns:
combinedcoltop3.extend(list(df[col].nlargest(3)))
combinedcoltop3.sort(reverse=True)
top3 = combinedcoltop3[:3]
您可以首先通过numpy将所有值展平到
,按降序排序,并通过索引返回top1d
数组。ravel3
值:
df1 = df.groupby(pd.Grouper(freq='1H')).apply(lambda x: -np.sort(-np.ravel(x))[:3])
print (df1)
TIME
2017-12-08 00:00:00 [78, 73, 67]
2017-12-08 01:00:00 [74, 70, 67]
2017-12-08 02:00:00 [72, 70, 61]
Freq: H, dtype: object
如果你想要专栏:
i = ['top1','top2','top3']
df1 = (df.groupby(pd.Grouper(freq='1H'))
.apply(lambda x: pd.Series(-np.sort(-np.ravel(x))[:3], index=i)))
print (df1)
top1 top2 top3
TIME
2017-12-08 00:00:00 78 73 67
2017-12-08 01:00:00 74 70 67
2017-12-08 02:00:00 72 70 61
我有下面的数据框- 我需要一个全新的数据帧,,有3列:1.0、2.0(结合2.0和4.0)和3.0(结合3.0和5.0)。 结果将是- 您可以预期合并列中不会有重叠的值;如果一行中的一列具有有效值,那么其他列将具有NaN值。 我试过了- 而且它并没有按预期的那样工作。有没有简单有效的方法来做到这一点?
问题内容: 我有以下数据框: 我需要以某种方式重塑数据框,以使每个id的前3列具有最高的值。结果将是这样的: 它显示了每本广告的前三名最畅销书。我已经使用R中的包完成了此操作,但是我正在寻找等效的pandas。 问题答案: 您可以用来查找每一行的 n个 最大项的索引: 产量
问题内容: 在 pandas groupby上发布了一个新的更通用的问题:每个组中的前3个值并存储在DataFrame中,并且在那里已经找到了可行的解决方案。 在此示例中,我创建了一个数据帧,其中的一些随机数据间隔为5分钟。我想创建一个数据框( df分组 ),其中列出了每小时的 3个最高值 。 即:从这一系列价值 我非常接近解决方案,但我找不到最后一步的正确语法。我到现在为止()的结果是: 我想从
问题内容: 我有两个Series,并且索引相同(非连续)。如何合并并成为DataFrame中的两列,并将其中一个索引保留为第三列? 问题答案: 我认为这是个不错的方法。如果存在它们,则使用“系列”的名称属性作为列(否则,将它们简单地编号): 注意:这扩展到2个以上的系列。
我有一个数组,我需要三个数中最大的一个数和各自的索引值。我有一个这样的数组: 如何找到最大的数字及其索引值?
我有一个名为的,它有4列,如下所示: 我想要的是找到关于类的每一列的最小值和最大值。换句话说,我希望得到一个类似于下面的结果: