【问题标题】:is there a better way to handle NaN values?有没有更好的方法来处理 NaN 值?
【发布时间】:2021-10-07 04:15:58
【问题描述】:

我有一个输入数据框

KPI_ID KPI_Key1 KPI_Key2 KPI_Key3 A (C602+C603) C601 75 B (C605+C606) C602 NaN C 75 L239+C602 NaN D (32*(C603+44)) 75 南 E L239 南 C601

我有一个指标 df

99 75 C604 C602 C601 C603 C605 C606 44 L239 32 患者 ID 1 1 0 1 0 1 0 0 0 1 0 1 2 0 0 0 0 0 0 1 1 0 0 0 3 1 1 1 1 0 1 1 1 1 1 1 4 0 0 0 0 0 1 0 1 0 1 0 5 1 0 1 1 1 1 0 1 1 1 1

来源:

input_df = pd.DataFrame({'KPI_ID': ['A','B','C','D','E'], 'KPI_Key1': ['(C602+C603)','(C605+ C606)','75','(32*(C603+44))','L239'] , 'KPI_Key2' : ['C601','C602','L239+C602','75',np. NaN] , 'KPI_Key3' : ['75',np.NaN,np.NaN,np.NaN,'C601']}) indicator_df = pd.DataFrame({'PatientID': [1,2,3,4,5],'99' : ['1','0','1','0','1'],' 75' : ['0','0','1','0','0'],'C604' : ['1','0','1','0','1'] ,'C602' : ['0','0','1','0','1'],'C601' : ['1','0','0','0','1 '],'C603' : ['0','0','1','1','1'],'C605' : ['0','1','1','0', '0'],'C606' : ['0','1','1','1','1'],'44' : ['1','0','1','0 ','1'],'L239' : ['0','0','1','1','1'], '32' : ['1','0','1', '0','1'],}).set_index('PatientID')

我的目标是创建这样的输出 df(通过根据 indicator_df 评估 input_df )

final_out_df: 患者 ID KPI_ID KPI_Key1 KPI_Key2 KPI_Key3 1 一个 0 1 0 2 一个 0 0 0 3 一个 2 0 1 4 一个 1 0 0 5 一个 2 1 0 1 B 0 0 0 2 乙 2 0 0 3 乙 2 1 0 ……………………

我非常接近,我的逻辑工作正常,除了我无法处理 input_df 中的 NaN 值。我能够生成 KPI_ID 'A' 的输出,因为三个公式(KPI_Key1、KPI_Key2、KPI_Key3 for 'A') 为空。但我无法为“B”生成它。除了使用虚拟变量代替 NaN 并在 indicator_df 中创建该行之外,我能做些什么吗? 这是我到目前为止所做的:

指标_df = 指标_df.astype('int32') final_out_df = pd.DataFrame() out_df = pd.DataFrame(index=indicator_df.index) out_df.reset_index(level=0, inplace=True) final_out_df = pd.DataFrame() #running 循环只用于'A',所以它不会失败 对于范围内的我(0,len(input_df)-4): 对于 ['KPI_Key1','KPI_Key2','KPI_Key3'] 中的 j: exp = input_df[j].iloc[i] temp_out_df=indicator_df.eval(re.sub(r'(\w+)', r'`\1`', exp)).reset_index(name=j) out_df['KPI_ID'] = input_df['KPI_ID'].iloc[i] out_df = out_df.merge(temp_out_df, on='PatientID', how='left') final_out_df=final_out_df.append(out_df) out_df = pd.DataFrame(index=indicator_df.index) out_df.reset_index(level=0, inplace=True)

【问题讨论】:

  • 我不明白为什么你的final_output_df 似乎是PatientIDKPI_ID 列的产物?除非input_df 中的列PatientID 不相关?
  • 没错! final_output_dg 中的 patientID 来自 indicator_df 。 input_df 中的 PatientiD 无关紧要。
  • 所以你的final_output_df 的总行数是input['KPI_ID'] x indicator_df['PatientID']
  • 没错!让我删除 input_df 中的 PatientID 列,以避免混淆。

标签: python pandas dataframe numpy


【解决方案1】:

NaN 替换为None 并创建一个局部变量字典以允许使用pd.eval 进行正确评估:

def eval_kpi(row):
    kpi = row.filter(like='KPI_Key').fillna('None')
    return pd.Series(pd.eval(kpi, local_dict=row['local_vars']), index=kpi.index)


final_out_df = indicator_df.astype(int).apply(dict, axis=1) \
                           .rename('local_vars').reset_index() \
                           .merge(input_df, how='cross')

final_out_df.update(final_out_df.apply(eval_kpi, axis=1))
final_out_df = final_out_df.drop(columns='local_vars') \
                           .sort_values(['KPI_ID', 'PatientID']) \
                           .reset_index(drop=True)

输出:

>>> final_out_df
    PatientID KPI_ID KPI_Key1 KPI_Key2 KPI_Key3
0           1      A      0.0      1.0     75.0
1           2      A      0.0      0.0     75.0
2           3      A      2.0      0.0     75.0
3           4      A      1.0      0.0     75.0
4           5      A      2.0      1.0     75.0
5           1      B      0.0      0.0      NaN
6           2      B      2.0      0.0      NaN
7           3      B      2.0      1.0      NaN
8           4      B      1.0      0.0      NaN
9           5      B      1.0      1.0      NaN
10          1      C     75.0      0.0      NaN
11          2      C     75.0      0.0      NaN
12          3      C     75.0      2.0      NaN
13          4      C     75.0      1.0      NaN
14          5      C     75.0      2.0      NaN
15          1      D   1408.0     75.0      NaN
16          2      D   1408.0     75.0      NaN
17          3      D   1440.0     75.0      NaN
18          4      D   1440.0     75.0      NaN
19          5      D   1440.0     75.0      NaN
20          1      E      0.0      NaN      1.0
21          2      E      0.0      NaN      0.0
22          3      E      1.0      NaN      0.0
23          4      E      1.0      NaN      0.0
24          5      E      1.0      NaN      1.0

【讨论】:

  • 我根据您的编辑更新了我的答案。请检查一下这是否符合您的期望?
  • 哈哈,当然,我刚刚做了编辑,但没问题。让我试着理解这一点并检查一下。 TIA
  • 这个想法很简单,可能与您的相同,但没有(可见)循环。我创建了一个像globals()locals()vars() 这样的字典。我在每一行(如ast.literal_eval)上使用pd.eval 来评估表达式。这里的技巧是用None(一个真正的python对象)替换NaN
  • 因此在 PatientID 1 的 final_out_df 中,KPI_Key3 值必须为 0 。因为在指标 Df 中,对于第 75 列下的 PAtientID,值为 0...
【解决方案2】:

我可以通过添加来解决它:

if exp == exp: 

在通过regex解析exp之前。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 2013-01-01
    • 2012-02-01
    • 2013-11-09
    • 1970-01-01
    • 2011-02-18
    相关资源
    最近更新 更多