我需要操作一个大的numpy数组,以便每个元素都在一定的范围内。
我可以识别无效的元素
v[np.where(v>upper_lim)]
v[np.where(v<lower_lim)]
或更简单地通过:
v[v>upper_lim]
v[v<lower_lim]
现在我想用符合条件的最接近(早期)样本替换满足此条件的每个元素。
e.g。
upper_lim=10
lower_lim=1
v=[1,-77,3,4,5,13213,6,7,8,1024]
应该给出
v=[1,1,3,4,5,5,6,7,8,8]
当没有元素可用之前无效值时,我需要替换为下一个有效元素
所以
upper_lim=10
lower_lim=1
v=[-7,1,2,3,-77]
应该给出
v=[1,1,2,3,3]
使用pandas的可能解决方案:
import pandas as pd
v=pd.DataFrame(v)
v[v>ul]=np.nan
v[v<ll]=np.nan
v=v.fillna(method='ffill').fillna(method='bfill')
v=v.flatten()
但使用pandas
不是我的选择
答案 0 :(得分:3)
pandas具有填充功能,这是你所描述的,但是你必须将你的数组转换为float,因为numpy int数组不能保存np.nan
值。
import pandas as pd
import numpy as np
upper = 10
lower = 1
v=np.array([1,-77,3,4,5,13213,6,7,8,1024])
s = pd.Series(v)
s[~((s>lower) & (s<upper))] = np.nan
s = s.fillna(method='pad')
# at this point the series is padded but the values are floats instead of
# ints, you can cast back to an int array if you wish
v2 = s.values.astype(int)
v2
# outputs:
array([1, 1, 3, 4, 5, 5, 6, 7, 8, 8])
更新
一个只有numpy的解决方案
# first we identify elements that are out of bounds and need to be filled from the data
mask = (v<lower) | (v>upper)
oob = np.where(mask)[0]
# for each oob value, we calculate the index that provides the fill-value using a forward fill or backward fill
def fillidx(i, mask_oob):
try:
if i == 0 or np.all(mask_oob[:i]):
# all elements from start are oob
raise IndexError()
n = -1 * (1 + np.argmin(mask_oob[:i][::-1]))
except (IndexError):
n = 1 + np.argmin(mask_oob[i+1:])
return i + n
fill = [fillidx(i, mask) for i in oob]
v[mask] = v[fill]
print(v)
使用第一个测试数组v = np.array([1,-77,3,4,5,13213,6,7,8,1024])
,输出如下:
[1 1 3 4 5 5 6 7 8 8]
使用第二个测试数组v = np.array([-7,1,2,3,-77])
输出以下内容:
[1 1 2 3 3]
有一个数组,其中连续值超出界限,前几个元素也超出界限,即v = np.array([-200,20,1,-77,3,4,5,13213,-200,6,7,8,1024])
我们得到以下输出:
[1 1 1 1 3 4 5 5 5 6 7 8 8]
答案 1 :(得分:0)
正如我在评论中所建议的那样,
v=[1,-77,3,4,5,13213,6,7,8,1024]
df=pd.DataFrame(v)
df[df>ul]=np.nan
df[df<ll]=np.nan
df=df.fillna(method='ffill')
v=np.array(df[0])
输出:
array([ 1., 1., 3., 4., 5., 5., 6., 7., 8., 8.])