df_train = minus_floor.copy()
df_test = high_target.copy()
FEATURES = ['c1', 'c2', 'c3']
TARGET = 'target'
PLOTS_IN_ROW = 2

sub_cols = 2 * PLOTS_IN_ROW # 항상 2의 배수로 할 것
sub_rows = (PLOTS_IN_ROW*len(FEATURES)+sub_cols-1) // sub_cols # 필요한 행 개수 계산
width = sub_cols * 3 # 그래프 가로 크기 조절
height = sub_rows * 3 # 그래프 세로 크기 조절

fig, axs = plt.subplots(sub_rows, sub_cols, figsize=(width,height))
axs = axs.flatten()
for idx in range(0, sub_cols*sub_rows-PLOTS_IN_ROW, PLOTS_IN_ROW):
    c = FEATURES[idx//PLOTS_IN_ROW]
    # PLOT TRAIN DISTRIBUTION COMPARED WITH TEST DISTRIBUTION
    sns.histplot(df_train[c],label='train', kde=True, stat='density', ax=axs[idx])
    sns.histplot(df_test[c],label='test', kde=True, stat='density', ax=axs[idx])
    axs[idx].legend()
    axs[idx].set_title(f"{c}")

    # PLOT TARGET RELATIONSHIP WITH BINNED NUMERIC FEATURES
    # 10개 구간별로 bucket(구간 번호)를 매겨 저장. retbins(구간 경계값을 반환 -> bin_edges)
    # labels=False: 구간의 label값은 반환 안 함.
    df_train['bucket'], bin_edges = pd.cut(df_train[c], bins=10, retbins=True, labels=False)
    all_buckets = range(10)
    # bucket 별로 target의 평균을 구함. (없는 bucket은 NaN으로 채움)
    bucket_means = df_train.groupby('bucket')[TARGET].mean().reindex(all_buckets)
    bin_midpoints = (bin_edges[:-1] + bin_edges[1:]) / 2 # marker를 그리기 위함.
    # (NaN 제거 후 그리기)
    valid_mask = ~bucket_means.isna()   
    axs[idx+1].plot(bin_midpoints[valid_mask], bucket_means[valid_mask], marker='o', linestyle='-')
    # plt.plot(bin_midpoints, bucket_means, marker='o', linestyle='-')
    axs[idx+1].set_xlabel(f'{c} (Binned)')
    axs[idx+1].set_ylabel('Mean TARGET')
    axs[idx+1].set_title(f'Mean TARGET per {c} (train)')
    axs[idx+1].set_xticks(bin_midpoints)
    axs[idx+1].tick_params(axis='x', rotation=45)
    axs[idx+1].grid()
# 남은 빈 서브플롯 숨기기 (필요한 그래프 개수보다 많은 경우)
for i in range(sub_cols*sub_rows - 2, len(axs)):
    fig.delaxes(axs[i])
plt.tight_layout()
plt.show()