【问题标题】:Get pandas dataframe where numeric values are not bigger/smaller than 5% of the previous value获取数值不大于/小于前一个值的 5% 的 pandas 数据框
【发布时间】:2020-11-19 22:16:42
【问题描述】:

我目前的解决方案如下:

    slices = []
    
    for idx in range(0, dataset.size):
        slice = dataset[idx:idx+4]

        if len(slice) < 4:
            break;

        # ---> check = []
        for val in slice[column].values: 
            delta_pos = round(slice[column].iloc[0] * 0.0005, 2)
            delta_neg = round(slice[column].iloc[0] * 0.0005, 2)
            check.append(delta_neg <= round(val, 2) - round(slice[column].iloc[0], 2) <= delta_pos)

        if(all(v == True for v in check)):
            slices.append(slice) # <----
                
    return slices

在这里,我检查 Pandas Dataframe 中每个可能的四项切片是否满足我的要求。如果是,则将切片添加到单独的 slices 数组中。

但在我看来,这段代码太难读了。还有更可靠、更简单的解决方案吗?


这是数据集的一小部分摘录:

VALUE
194.7200000
194.7600000
195.0500000
194.9500000
195.0800000
195.1700000
195.0700000
195.2200000
195.2000000
195.2100000
195.2500000
195.1600000
194.6200000
194.6400000
194.9000000
194.8200000
194.8000000
194.6400000
194.7800000
194.6600000
194.7000000
194.6300000
...

【问题讨论】:

  • 是的,我只是想让我想简化的代码变成粗体
  • 啊,好的。粗体在代码环境中不起作用,我通常添加 # &lt;---- 或 smth 来标记位置:)
  • 能否分享一个dataset 的小例子,以便我们自己运行代码?
  • 你希望我如何分享一个例子?您可以使用 dropmefiles 服务吗?
  • 只需打印并分享dataset.iloc[:10, :] 即可获得包含所有列的前 10 行

标签: python pandas dataframe slice


【解决方案1】:

您可以使用shift 和一些索引在两行代码中优雅地实现这一点。假设我们有一个数据框 df 定义为:

df=pd.DataFrame({'VALUE':{0:194.72, 1:194.76, 2:195.05, 3:194.95, 4:195.08, 5:195.17,
                          6:195.07, 7:195.22, 8:195.2, 9:195.21, 10:195.25,11:195.16,
                          12:194.62,13:194.64,14:194.9,15:194.82,16:194.8,17:194.64,
                          18:194.78,19:194.66,20:194.7,21:194.63}})

我们可以将所有值的位置移动一位以获得'previous'值:

df_shifted = df.shift(1, fill_value=df.VALUE[0])

现在,我们可以在原始数据框中选择容差为 5% 的值:

df_within_5percent = df[abs(df.VALUE - df_shifted.VALUE)< 0.05]

就是这样! df_within_5percent 包含 5% 公差 w.r.t 内的值。之前的值。

【讨论】:

  • 我虚心地相信没有比这更优雅的了
【解决方案2】:

您可以使用rolling 创建所有 4 个连续值的组。要应用逻辑,您需要将其重写为接受一系列(4 个值)的函数


In [17]: def select_slices(s): 
    ...:     for val in s.values: 
    ...:         delta =  round(s.iloc[0] * 0.0005, 2) 
    ...:         if not (-delta <= round(val, 2) - round(s.iloc[0], 2) <= delta): 
    ...:             return 1 
    ...:     slices.append(s) 
    ...:     return 0 
    ...:                                                                                                                                                                                                           
In [18]: s.rolling(4).apply(select_slices)  

rolling 期望一个标量返回值,因此相当简单的return 语句。我还冒昧地通过消除重复代码并提前返回来缩短您的代码。

您可以通过删除循环并检查最大值和最小值是否在您想要的范围内来获得更清洁。

根据您的示例数据,这给出了

In [19]: slices                                                                                                                                                                                                    
Out[19]: 
[5    195.17
 6    195.07
 7    195.22
 8    195.20
 dtype: float64,
 7     195.22
 8     195.20
 9     195.21
 10    195.25
 dtype: float64,
 8     195.20
 9     195.21
 10    195.25
 11    195.16
 dtype: float64]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-04
    • 2019-02-11
    • 2013-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多