簡體   English   中英

如何排除數據框中的連續值

[英]How to exclude consecutive values in dataframe

使用此代碼:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

pd.options.mode.chained_assignment = None
pd.options.display.float_format = '{:.2f}'.format
dateparse = lambda x: pd.datetime.strptime(x,'%Y%m%d%H%M')
a = pd.read_csv(r'C:\Users\Leonardo\Desktop\Nova pasta\TU_boia0401.out', parse_dates = ['data'], index_col = 0, date_parser = dateparse)

輸出是這樣的:

index               hs
2015-02-23 14:50:00 0.99
2015-02-23 15:50:00 0.96
2015-02-23 16:50:00 1.04
2015-02-23 17:50:00 0.96
.                   .
.                   .
.                   .
2017-09-01 12:40:00 1.25

直到這里一切都很好,但通過繪制它來分析所有數據的事情被注意到了。 這就是問題:

在此輸入圖像描述

在2015-03-06附近可以看到,有很多不應該存在的重復值。 查看數據框架可以看到:

2015-03-04 10:50:00 1.18
2015-03-04 11:50:00 1.18
2015-03-04 12:50:00 1.18
2015-03-04 13:50:00 1.18

它在數據幀中重復了很多次。 主要目標是過濾這些BAD數據並將其從數據幀中刪除,並將np.nan設置為每個連續3次(或者也超過3次)重復整個數據幀的值。 輸出預期是這樣的:

index               hs
2015-02-23 14:50:00 0.99
2015-02-23 15:50:00 0.96
2015-02-23 16:50:00 1.04
2015-02-23 17:50:00 0.96
.                   .
.                   .
.                   .
2015-03-04 10:50:00 1.18
2015-03-04 11:50:00 nan
2015-03-04 12:50:00 nan
2015-03-04 13:50:00 nan
.                   .
.                   .
.                   .
2016-01-20 12:40:00 0.98
2016-01-20 12:50:00 nan
2016-01-20 13:00:00 nan
2016-01-20 13:10:00 nan
.                   .
.                   .
.                   .
2017-09-01 12:40:00 1.25

如果有人可以提供幫助,將會感激不盡。

這將NaN設置為大於或等於n所有前向重復(例如3)。

# Set-up.
np.random.seed(0)
df = pd.DataFrame(np.random.randn(10, 1), index=pd.DatetimeIndex(start='2017-01-01', freq='min', periods=10), columns=['hs'])
df.loc[3:6] = df.iat[2, 0]
df.loc[8:10] = df.iat[7, 0]

>>> df
                           hs
2017-01-01 00:00:00  1.764052
2017-01-01 00:01:00  0.400157
2017-01-01 00:02:00  0.978738
2017-01-01 00:03:00  0.978738  # Duplicate x3
2017-01-01 00:04:00  0.978738  # Duplicate x3
2017-01-01 00:05:00  0.978738  # Duplicate x3
2017-01-01 00:06:00  0.950088
2017-01-01 00:07:00 -0.151357
2017-01-01 00:08:00 -0.151357  # Duplicate x2
2017-01-01 00:09:00 -0.151357  # Duplicate x2

# Set forward duplicates to NaN.
n = 3
bool_mask = df.hs.shift() == df.hs
df = df.assign(
    mask=bool_mask,
    group=(bool_mask != bool_mask.shift()).cumsum())
filter_groups = df.groupby('group')[['mask']].sum().query('mask >= {}'.format(n)).index
df.loc[df.group.isin(filter_groups), 'hs'] = np.nan
df = df[['hs']]
>>> df
                           hs
2017-01-01 00:00:00  1.764052
2017-01-01 00:01:00  0.400157
2017-01-01 00:02:00  0.978738
2017-01-01 00:03:00       NaN
2017-01-01 00:04:00       NaN
2017-01-01 00:05:00       NaN
2017-01-01 00:06:00  0.950088
2017-01-01 00:07:00 -0.151357
2017-01-01 00:08:00 -0.151357
2017-01-01 00:09:00 -0.151357

它創建一個布爾掩碼來檢查重復項,並通過assign將此列添加到數據幀。 該代碼還添加了一個group列,用於查找連續的重復區域(使用shift-cumsum模式創建)。 將groupby應用於組,將mask布爾值相加。 這給出了連續重復的次數。 然后使用query過濾這些結果以定位重復計數大於或等於n (例如3)。

最后,數據幀使用loc將連續計數超過3的組的hs設置為NaN 通過df = df[['hs']]從數據幀中獲取hs來排除臨時列。

設定
借用@ Alexander的數據框

np.random.seed(0)
df = pd.DataFrame(
    np.random.randn(10, 1),
    pd.DatetimeIndex(start='2017-01-01', freq='min', periods=10),
    ['hs'])

df.loc[4:6] = df.iat[3, 0]


使用pd.DataFrame.maskpd.DataFrame.diff
注意:這是一種通用解決方案,可以同時對所有列執行相同的任務。

df.mask(df.diff() == 0)

                           hs
2017-01-01 00:00:00  1.764052
2017-01-01 00:01:00  0.400157
2017-01-01 00:02:00  0.978738
2017-01-01 00:03:00  2.240893
2017-01-01 00:04:00       NaN
2017-01-01 00:05:00       NaN
2017-01-01 00:06:00  0.950088
2017-01-01 00:07:00 -0.151357
2017-01-01 00:08:00 -0.103219
2017-01-01 00:09:00  0.410599

更大的例子

np.random.seed([3,1415])
df = pd.DataFrame(
    np.random.randint(5, size=(10, 5)).astype(float),
    pd.DatetimeIndex(start='2017-01-01', freq='min', periods=10),
).add_prefix('col')

df

                     col0  col1  col2  col3  col4
2017-01-01 00:00:00   0.0   3.0   2.0   3.0   2.0
2017-01-01 00:01:00   2.0   3.0   2.0   3.0   0.0
2017-01-01 00:02:00   2.0   0.0   0.0   4.0   0.0
2017-01-01 00:03:00   2.0   2.0   0.0   4.0   1.0
2017-01-01 00:04:00   3.0   2.0   4.0   4.0   4.0
2017-01-01 00:05:00   4.0   3.0   3.0   3.0   4.0
2017-01-01 00:06:00   3.0   1.0   3.0   0.0   4.0
2017-01-01 00:07:00   4.0   2.0   2.0   0.0   2.0
2017-01-01 00:08:00   4.0   0.0   4.0   1.0   4.0
2017-01-01 00:09:00   4.0   2.0   2.0   0.0   2.0

df.mask(df.diff() == 0)

                     col0  col1  col2  col3  col4
2017-01-01 00:00:00   0.0   3.0   2.0   3.0   2.0
2017-01-01 00:01:00   2.0   NaN   NaN   NaN   0.0
2017-01-01 00:02:00   NaN   0.0   0.0   4.0   NaN
2017-01-01 00:03:00   NaN   2.0   NaN   NaN   1.0
2017-01-01 00:04:00   3.0   NaN   4.0   NaN   4.0
2017-01-01 00:05:00   4.0   3.0   3.0   3.0   NaN
2017-01-01 00:06:00   3.0   1.0   NaN   0.0   NaN
2017-01-01 00:07:00   4.0   2.0   2.0   NaN   2.0
2017-01-01 00:08:00   NaN   0.0   4.0   1.0   4.0
2017-01-01 00:09:00   NaN   2.0   2.0   0.0   2.0

如果要控制窗口大小,可以使用滾動對象。 這個想法是,如果n個連續的元素是相同的,它們的標准偏差將是0.其余的是

successive = (ser.where(np.isclose(ser.rolling(3).std(), 0, atol=10**-6))
                 .bfill(limit=2).notnull())
ser[successive] = np.nan

對於系列, ser

ser = pd.Series([1, 1, 1, 2, 2, 2, 1, 1, 3, 3, 3, 3, 1, 2, 1, 3, 2, 1, 1, 1])

這收益率

0     NaN
1     NaN
2     NaN
3     NaN
4     NaN
5     NaN
6     1.0
7     1.0
8     NaN
9     NaN
10    NaN
11    NaN
12    1.0
13    2.0
14    1.0
15    3.0
16    2.0
17    NaN
18    NaN
19    NaN

你可以做一個for循環來跟蹤重復的事情:

replacement_value = np.nan
last_value = None
number_of_repetitions = 0
for index in range(len(values)):
   if value == last_value:
       if number_of_repetitions == 2: 
       #if we previously had 2 repetitions, we should replace both the current and the previous values
          values[index-1] = replacement_value
          values[index] = replacement_value
       if number_of_repetitions == 3: 
          #if this is the third or more repetition, we've already replaced the previous value, so we just need to handle the current one
          values[index] = replacement_value
       else:
          number_of_repetitions = number_of_repetitions+1
          #if it hasn't reach 3 yet, we should increment every time we see a repetition
          #but we don't need to keep track after 3      
   else: 
      #if this is a new value, we should reset
      number_of_repetitions = 1 
      last_value = value

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM