[英]Grouping floating point numbers
我有一个应用程序,在该应用程序中,我需要根据时间戳将一个数据列表(当前在pandas.DataFrame
)平均化,该时间戳可能是浮点值。 例如,我可能需要将以下df
平均为0.3
秒:
+------+------+ +------+------+
| secs | A | | secs | A |
+------+------+ +------+------+
| 0.1 | .. | | 0.3 | .. | <-- avg of 0.1, 0.2, 0.3
| 0.2 | .. | --> | 0.6 | .. | <-- avg of 0.4, 0.5, 0.6
| 0.3 | .. | | ... | ... | <-- etc
| 0.4 | .. | +------+------+
| 0.5 | .. |
| 0.6 | .. |
| ... | ... |
+------+------+
当前,我正在使用以下(最小)解决方案:
import pandas as pd
import numpy as np
def block_avg ( df : pd.DataFrame, duration : float ) -> pd.DataFrame:
grouping = (df['secs'] - df['secs'][0]) // duration
df = df.groupby( grouping, as_index=False ).mean()
df['secs'] = duration * np.arange(1,1+len(df))
return df
它对于整数duration
s来说效果很好,但是块边缘的浮点值可能落在错误的一侧。 一个简单的测试,即正确创建了块是对数据已经存在的相同duration
求平均(在此示例中0.1
)。 这应该返回输入,但通常不会。 (例如x=.1*np.arange(1,20); (xx[0])//.1)
。)
我发现此方法的错误通常是LSB为1低,因此尝试性的解决方法是将np.spacing(df['secs'])
到grouping
的分子。 (即x=.1*np.arange(1,20); all( (xx[0]+np.spacing(x)) // .1 == np.arange(19) )
返回True
。)
但是,我担心这不是一个可靠的解决方案。 是否有更好或更好的方法可以对通过上述测试的浮标进行分组?
我遇到了(也许更直接)算法的类似问题,该算法使用x[ (duration*i < x) & (x <= duration*(i+1)) ]
分组并在适当的范围内循环i
。
为了更加小心(避免浮动不准确),在进行分组之前,我会提前四舍五入:
In [11]: np.round(300 + df.secs * 1000).astype(int) // 300
Out[11]:
0 1
1 1
2 1
3 2
4 2
5 2
Name: secs, dtype: int64
In [12]: (np.round(300 + df.secs * 1000).astype(int) // 300) * 0.3
Out[12]:
0 0.3
1 0.3
2 0.3
3 0.6
4 0.6
5 0.6
Name: secs, dtype: float64
In [13]: df.groupby(by=(np.round(300 + df.secs * 1000).astype(int) // 300) * 0.3)["A"].sum()
Out[13]:
secs
0.3 1.753843
0.6 2.687098
Name: A, dtype: float64
我更喜欢使用timedelta:
In [21]: s = pd.to_timedelta(np.round(df["secs"], 1), unit="S")
In [22]: df["secs"] = pd.to_timedelta(np.round(df["secs"], 1), unit="S")
In [23]: df.groupby(pd.Grouper(key="secs", freq="0.3S")).sum()
Out[23]:
A
secs
00:00:00 1.753843
00:00:00.300000 2.687098
或resample
:
In [24]: res = df.set_index("secs").resample("300ms").sum()
In [25]: res
Out[25]:
A
secs
00:00:00 1.753843
00:00:00.300000 2.687098
您可以设置索引来更正标签*
In [26]: res.index += np.timedelta64(300, "ms")
In [27]: res
Out[27]:
A
secs
00:00:00.300000 1.753843
00:00:00.600000 2.687098
*应该有一种方法可以通过重采样参数来设置,但是它们似乎不起作用...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.