根据另一个DF替换熊猫列值

时间:2020-02-25 13:05:56

标签: python pandas pandas-groupby

我有一个样本DF:

sample_df = pd.DataFrame(np.random.randint(1,20,size=(6, 2)), columns=list('AB'))
sample_df["A_cat"] = ["ind","sa","sa","sa","ind","ind"]
sample_df["B_cat"] = ["sa","ind","ind","sa","sa","sa"]
sample_df

OP:

    A   B   A_cat   B_cat
0   12  8   ind     sa
1   12  11  sa      ind
2   7   19  sa      ind
3   5   11  sa      sa
4   11  7   ind     sa
5   6   18  ind     sa

我还有另一个样本DF 2,我正在尝试根据条件替换列值:

sample_df2 = pd.DataFrame()
sample_df2["A_cat"] = ["sa","ind","ind","sa","sa","ind"]
sample_df2["B_cat"] = ["ind","sa","sa","ind","sa","sa"]
sample_df2

OP:

    A_cat   B_cat
0   sa     ind
1   ind    sa
2   ind    sa
3   sa     ind
4   sa     sa
5   ind    sa

条件:

The value in sample_df2 should be replaced by taking a groupby mean of that value in sample_df.

例如,sample_df2(0,A_cat) = sa应该替换为sample_df.groupby(["A_cat"])["A"].mean() for group value sa

转换后,{p}中A_cat的列sample_df2

OP示例为:

sample_df2["A_cat"] = [8.0000,9.666667,9.666667,8.000,8.000,9.666667]

为此,我已经做了很长的循环解决方案,任何有关熊猫方法的建议都很棒!

2 个答案:

答案 0 :(得分:1)

请检查以下代码并比较经过时间

import time

start_time = time.time()
categorical_cols = [col for col in df1.columns if len(col.split('_')) > 1]
numerical_cols = df1[df1.columns.difference(categorical_cols)].columns
unique_groups = df1['A_cat'].unique().tolist() # returns [ind, sa]

for cat, num in zip(categorical_cols, numerical_cols):
    for group in unique_groups:
        df2.loc[df2[cat] == group, cat] = df1.groupby(cat)[num].mean().loc[group]

print("Elapsed time:", time.time() - start)

答案 1 :(得分:0)

这有点笨拙,但是可以用:

实际计算一次:

category_value_means = sample_df2.apply(
    lambda column: sample_df.groupby(column.name)[column.name.split('_')[0]].mean())

其输出是:

    A_cat       B_cat
ind 9.666667    15
sa  8.000000    11

然后,只需要进行一些“查找”即可:

sample_df2.apply(lambda column: column.apply(lambda value: category_value_means[column.name][value]))

输出为:

    A_cat   B_cat
0   8.000000    15
1   9.666667    11
2   9.666667    11
3   8.000000    15
4   8.000000    11
5   9.666667    11