<jupyter_start><jupyter_text>Calculate factor effect Values<jupyter_code>def get_factor_effect(factor_list, output_list, max_inp=1, min_inp=-1):  
    # same as 2factor2levels code
    mean_weightage = len(output_list)/2
    
    pos_effect = 0
    pos_counts = 0
    neg_effect = 0
    neg_counts = 0
    for fact_val, out_val in zip(factor_list, output_list):
        if fact_val == max_inp:    
            pos_effect += out_val
            pos_counts += 1
        
        elif fact_val == min_inp:
            neg_effect -= out_val
            neg_counts += 1
    
        else:
            print("something wrong in input")
    
    total_counts = pos_counts + neg_counts
    factor_effect = (pos_effect*neg_counts/total_counts) + (neg_effect*pos_counts/total_counts)
    # print('counts ', pos_counts, neg_counts)
    # print('effects ', pos_effect, neg_effect)
    
    return factor_effect/mean_weightage
_factor_names = [f'f{ind}' for ind in range(1, 13+1)]
_output_names = [f'o{ind}' for ind in range(1, 3+1)]

# rows are f1, f2, .. 13 rows, cols are o1, o2 .. 3 columns
output_df = pd.DataFrame(np.nan, columns=_output_names, index=_factor_names)

for factor_name, _row in output_df.iterrows():
    for output_name in _row.keys():
        _factor_effect = get_factor_effect(df[factor_name].tolist(), df[output_name].tolist())
        output_df.loc[factor_name][output_name] = _factor_effect

output_df['o_com'] = 0
for output_name in _output_names:
    output_df['o_com'] += abs(output_df[output_name])
output_df['o_com'] = output_df['o_com']/len(_output_names)

com_avg = output_df['o_com'].mean()
print(f'average of composite factor is {com_avg}\n\n')
print(output_df)
output_df.to_csv('../data/results_v2.csv')
# df['f6'].value_counts()
#  get_factor_effect(df['f6'].tolist(), df['o1'].tolist())<jupyter_output><empty_output><jupyter_text>calculate interaction effects<jupyter_code>def get_factors_interaction_effect(factor1_list, factor2_list, output_list, max_inp=1, min_inp=-1):
    if not(set(factor1_list) == set(factor2_list) == {-1, 1}):
        raise ValueError('invalid factor values')

    high_interaction = 0
    low_interaction = 0
    high_counts = 0
    low_counts = 0
    mean_weightage = len(output_list) / 2

    for f1_val, f2_val, out_val in zip(factor1_list, factor2_list, output_list):
        if f2_val == max_inp:
            high_interaction = high_interaction + out_val if f1_val == max_inp else high_interaction - out_val
            high_counts += 1

        elif f2_val == min_inp:
            low_interaction = low_interaction + out_val if f1_val == max_inp else low_interaction - out_val
            low_counts += 1

    total_counts = high_counts + low_counts
#     interaction_effect = (high_interaction*low_counts/total_counts) + (low_interaction*high_counts/total_counts)
    interaction_effect = high_interaction - low_interaction

    interaction_effect = interaction_effect / mean_weightage
    return interaction_effect
# rows are f1, f2, .. 13 rows, cols are f1, f2, .. 13 columns
output_int_dfs = dict.fromkeys(_output_names, None)

for output_name in _output_names:
    _output_int_df = pd.DataFrame(np.nan, columns=_factor_names, index=_factor_names)
    
    for factor1_name, _row in _output_int_df.iterrows():
        for factor2_name in _row.keys():
            _factor_int_effect = 0
            if factor1_name != factor2_name:
                _factor_int_effect = get_factors_interaction_effect(
                    df[factor1_name].tolist(), 
                    df[factor2_name].tolist(), 
                    df[output_name].tolist()
                )
            _output_int_df.loc[factor1_name][factor2_name] = _factor_int_effect
#             _output_int_df.loc[factor2_name][factor1_name] += _factor_int_effect
    
    output_int_dfs[output_name] = _output_int_df
output_int_dfs['o1']
def scale_interaction_effects(df_raw, feature_range):
    # Using MinMaxScaler
    df_len = len(df_raw)
    min_max_scaler = MinMaxScaler(feature_range=feature_range)
    
    # Stack everything into a single column to scale by the global min / max
    tmp = df_raw.to_numpy().reshape(-1,1)
    mid_value = (df_raw.max().max() + df_raw.min().min())/2
    tmp = np.where(tmp == 0, mid_value, tmp)
    
    scaled_values = min_max_scaler.fit_transform(tmp).reshape(df_len, df_len)
    scaled_values = np.round(scaled_values, 4)
    scaled_values = np.where(scaled_values == 0, 0, scaled_values)
    
    return pd.DataFrame(scaled_values, columns=df_raw.columns, index=df_raw.index)
factor_name_map = {
 'f1': 'h1',
 'f2': 'h2',
 'f3': 'h3',
 'f4': 'theta1',
 'f5': 'theta2',
 'f6': 'theta3',
 'f7': 'delta1',
 'f8': 'delta2',
 'f9': 'delta3',
 'f10': 'ag',
 'f11': 'l1',
 'f12': 'l2',
 'f13': 'l3'
}
output_name_map = {
 'o1': 'T ripple',
 'o2': 'Efficiency',
 'o3': 'T avg',
}
cbar_ticks = [x/10 for x in range(-10, 12, 2)]
xy_ticks = [factor_name_map[f] for f in _factor_names]
# mask = np.zeros((13, 13))
# mask[np.triu_indices_from(mask)] = True

f,ax = plt.subplots(1,3,figsize=(45,15), dpi = 150, facecolor='w', edgecolor='k')
for ind, _out in enumerate(_output_names):
    value_to_map = output_int_dfs[_out]
    value_to_map = scale_interaction_effects(output_int_dfs[_out], feature_range=(-1, 1))
    
    # assign into subplot
    ax[ind] = sns.heatmap(value_to_map, annot=True, cmap='RdYlGn',linewidths=0.4,
                          cbar_kws={'label': 'scale', 'ticks': cbar_ticks},
                          xticklabels = xy_ticks, yticklabels = xy_ticks,
                          ax=ax[ind]).set_title(f"\nFactor interaction effects for {output_name_map[_out]}\n",fontsize=20)
plt.show()<jupyter_output>findfont: Font family ['Helvetica'] not found. Falling back to DejaVu Sans.
findfont: Font family ['Helvetica'] not found. Falling back to DejaVu Sans.
findfont: Font family ['Helvetica'] not found. Falling back to DejaVu Sans.
{'fraction_non_alphanumeric': 0.12148424262961707, 'fraction_numerical': 0.02338190443917316, 'mean_word_length': 3.565351894818252, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '423991', 'license': 'MIT', 'n_tokens_mistral': 2226, 'n_tokens_neox': 2151, 'n_words': 426, 'path': 'code/notebooks/06 13factor_2levels interaction effects.ipynb', 'repo_name': 'krishnansr/doe-sensitivity-analysis', 'size': '5902'}