我希望改善代码的一部分,以查找下方和上方形成的范围的上下栏值(数据透视列)。这是数据和我的代码的示例:
df =
10 20 30 40 50 60 pivot
2020-01-01 4 0 9 7 7 0 25
2020-01-02 0 3 7 0 8 0 45
2020-01-03 5 7 0 0 7 8 42
2020-01-04 8 12 0 8 0 7 32
2020-01-05 12 22 0 7 0 12 43
2020-01-06 1 0 0 12 0 0 27
2020-01-07 4 0 32 8 7 0 18
2020-01-08 23 32 23 12 12 12 23
代码应在列中水平查找值,完成设置点后,继续在(右)设置点上下(左)寻找水平范围,将零丢弃以形成一些间隙(这是设计的一部分)此代码是为了跳过此空白)。所以最终的df
可能看起来像这样:
10 20 30 40 50 60 pivot lowBelow highBelow lowAbove highAbove
2020-01-01 4 0 9 7 7 0 25 10 10 30 50
2020-01-02 0 3 7 0 8 0 45 20 30 50 50
2020-01-03 5 7 0 0 7 8 42 10 20 50 60
2020-01-04 8 12 0 8 0 7 32 10 20 40 40
2020-01-05 12 22 0 7 0 12 43 40 40 12 12
2020-01-06 1 0 0 12 0 0 27 10 10 40 40
2020-01-07 4 0 32 8 7 0 18 10 10 30 50
2020-01-08 23 32 23 12 12 12 23 10 20 30 60
我开发的代码如下:
def rangeLevels(pivot, ranges, thd=0):
ranges.columns = ['level','thd']
ranges['gap'] = np.where(ranges.thd>thd, 1, 0)
ranges['group'] = ranges.gap.ne(ranges.gap.shift()).cumsum()
ranges['gap'] = ranges.gap * ranges.group.map(ranges.groupby(['group']).gap.count())
try:
above = ranges[(ranges.level>pivot) & (ranges.thd>thd)]
pAbove = above.group.iloc[np.argmin((np.array(above.level) - pivot)**2)]
highAbove = above.level[above.group==pAbove].max()
lowAbove = above.level[above.group==pAbove].min()
below = ranges[(ranges.level<pivot) & (ranges.thd>thd)]
pBelow = below.group.iloc[np.argmin((below.level - pivot)**2)]
highBelow = below.level[below.group==pBelow].max()
lowBelow = below.level[below.group==pBelow].min()
return pd.Series([highAbove, lowAbove, highBelow, lowBelow])
except:
pass
columns = df.columns[:-4]
df2 = [
rangeLevels(
df.pivot.iloc[row],
pd.DataFrame({
'thd': df[columns].iloc[row]
}).reset_index().astype(int).rename(columns={'index':'level'}) )
for row in range(len(df))]
我使用了try
/ except
句子,因为有时我在空数组中有一些错误。我决定使用 listcomp ,因为我读它比使用map + lambda函数要快。但是,我很感谢您的评论和改进此功能的方法,我没有在 numpy 中使用向量的经验,我开始通过使用 pandas 进行改进,但是对于我的大型数据集我认为有更好的方法。
谢谢。
答案 0 :(得分:0)
我会考虑使用apply函数。
def range_levels(row):
pivot = getattr(row, "pivot")
all_cols = [10, 20, 30, 40, 50, 60]
cols_below = [i for i in all_cols if i < pivot]
cols_above = [i for i in all_cols if i > pivot]
values_below = [getattr(row, str(i)) for i in cols_below]
values_above = [getattr(row, str(i)) for i in cols_above]
low_below = min([i for i in values_below if i > 0])
low_above = min([i for i in values_above if i > 0])
high_below = min([i for i in values_below if i > 0])
high_above = min([i for i in values_above if i > 0])
return [low_below, high_below, low_above, high_above]
df["range_levels"] = df.apply(range_levels, axis=1)
df[["low_below"
,"high_below"
,"low_above"
,"high_above"]] = pd.DataFrame(df.range_levels.tolist(), index= df.index)
这应该是一个很好的入门。