使用特定范围条件将值与列匹配

Matching values to columns using specific range criteria

我正在使用以下 table 尝试以动态方式将“给定”值与“年”列匹配,然后找到超过 70% 标记的年数。

data = {
    'Given' : [0.45, 0.39, 0.99, 0.58, None],
    'Year 1' : [0.25, 0.15, 0.3, 0.23, 0.25],
    'Year 2' : [0.39, 0.27, 0.55, 0.3, 0.4],
    'Year 3' : [0.43, 0.58, 0.78, 0.64, 0.69],
    'Year 4' : [0.65, 0.83, 0.95, 0.73, 0.85],
    'Year 5' : [0.74, 0.87, 0.99, 0.92, 0.95]
}
   
df = pd.DataFrame(data)

print(df)

Output:

   Given  Year 1  Year 2  Year 3  Year 4  Year 5
0   0.45    0.25    0.39    0.43    0.65    0.74
1   0.39    0.15    0.27    0.58    0.83    0.87
2   0.99    0.30    0.55    0.78    0.95    0.99
3   0.58    0.23    0.30    0.64    0.73    0.92
4    NaN    0.25    0.40    0.69    0.85    0.95


如果“给定”值小于“给定”任一侧两年之间距离的 75%,我将尝试将“给定”值与较低年份相匹配。

非正统视觉辅助:

下一年 ------ 75% --> 上一年

示例:如果“给定”是 0.17,“第 1 年”是 0.1,“第 2 年”是 0.2,那么它仍将映射到“第 1 年”,因为 0.17 < 0.175(两者之间的距离的 75%两者), 输出 "1".

如果“给定”>=70%,则输出“满”。而如果"given"为NaN,则输出第一年70%以上。

示例输出:

   Given  Year 1  Year 2  Year 3  Year 4  Year 5 Output
0   0.45    0.25    0.39    0.43    0.65    0.74    2.0
1   0.39    0.15    0.27    0.58    0.83    0.87    2.0
2   0.99    0.30    0.55    0.78    0.95    0.99   full
3   0.58    0.23    0.30    0.64    0.73    0.92    1.0
4    NaN    0.25    0.40    0.69    0.85    0.95      4

这是我试图编辑以匹配第一个标准的答案(它仍然提供相同的输出,但不遵循 75% 的围栏):

import pandas as pd
import numpy as np

pct_70 = (df.T.reset_index(drop=True).T > .7).idxmax(axis=1)

nearest_col = ((df.iloc[:,1:].T.reset_index(drop=True).T 
 - pd.concat([df.iloc[:,0]] * len(df.columns[1:]), axis=1)
  .T.reset_index(drop=True).T)).abs().idxmin(axis=1) 

output = pct_70 - nearest_col - 1
# Conditionally apply the output series
df['Output'] = np.select([output.gt(0),output.lt(0),output.isnull()],
                          [output, 'full', pct_70],np.nan)

我正在尝试更改行

nearest_col = ((df.iloc[:,1:].T.reset_index(drop=True).T 
 - pd.concat([df.iloc[:,0]] * len(df.columns[1:]), axis=1)
  .T.reset_index(drop=True).T)).abs().idxmin(axis=1)

从数学上讲我知道我们会合并

0.75*(df.iloc[:,1:].T.reset_index(drop=True).T 
 - pd.concat([df.iloc[:,0]])

但我不确定如何将其编辑到代码中 - 作为一个 python 初学者,我现在不知所措..

感谢所有帮助。

总结一下,三种情况:

情况 1:给定超过 70% -> 输出“已满” 情况 2:给定低于 70% -> 如果小于 3/4 则匹配较低年份 -> 输出年数直到 70% 或更高 案例 3:给定为 NaN -> 输出年数,直到 70% 或更高

这是一种使用 numpy 广播的方法:

import numpy as np

# 75% rule.
thresholds = df + df.diff(-1, axis=1).abs() * 0.75
below_75 = (df['Given'].to_numpy()[:, None] - thresholds.to_numpy()) < 0
min_year = thresholds.where(below_75).drop(columns=['Given']).idxmin(axis=1).str.replace('Year ', '').astype(float)
min_year = df.where(df > 0.7).drop(columns=['Given']).idxmin(axis=1).str.replace('Year ', '').astype(float) - min_year

# 70% rule.
min_year.loc[df['Given'] > 0.7] = 'full'

# NaN rule.
min_year.loc[df['Given'].isna()] = df.where(df > 0.7).drop(columns=['Given']).idxmin(axis=1).str.replace('Year ', '').astype(float)

df['Output'] = min_year

print(df)
   Given  Year 1  Year 2  Year 3  Year 4  Year 5 Output
0   0.45    0.25    0.39    0.43    0.65    0.74    2.0
1   0.39    0.15    0.27    0.58    0.83    0.87    2.0
2   0.99    0.30    0.55    0.78    0.95    0.99   full
3   0.58    0.23    0.30    0.64    0.73    0.92    1.0
4    NaN    0.25    0.40    0.69    0.85    0.95    4.0

另一个数据集:

如果您不遵循 75% 规则,您的示例数据也具有相同的输出,这里是另一个示例行(输出应为 2):

   Given  Year 1  Year 2  Year 3  Year 4  Year 5
0    0.31    0.23     0.3    0.64    0.73    0.92

用你的方法输出:

   Given  Year 1  Year 2  Year 3  Year 4  Year 5 Output
0    0.31    0.23     0.3    0.64    0.73    0.92      1

在这个答案中输出解决方案:

   Given  Year 1  Year 2  Year 3  Year 4  Year 5 Output
0    0.31    0.23     0.3    0.64    0.73    0.92    2.0