[英]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.mask
和pd.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.