熊猫-根据其他列中的值计算条件的列平均值

时间:2019-03-21 00:41:28

标签: python pandas if-statement iteration

我努力在数据框中创建新列,这是通过每一行数据框并根据某些条件计算平均值的结果。 数据框就是这样

ID, 1_a, 1_b, 1_c, 2_a, 2_b, 2_c, 3_a, 3_b, 3_c 
0, 0, 145, 0.8, 0, 555, 0.7, 1, 335, 0.7
1, 1, 222, 0.9, 1, 224, 0.4, 1, 555, 0.6
3, 1, 111, 0.3, 0, 222, 0.5, 1, 999, 0.7 

我希望得到以下结果:

ID, 1_a, 1_b, 1_c, 2_a, 2_b, 2_c, 3_a, 3_b, 3_c, NEW
0, 0, 145, 0.8, 0, 555, 0.7, 1, 335, 0.7, 0.7
1, 1, 222, 0.8, 1, 224, 0.4, 1, 555, 0.6, 0.6
3, 1, 111, 0.3, 0, 222, 0.5, 1, 999, 0.7, 0.5

逻辑如下。

If 1_a is 1, keep value in 1_c, if not ignore
If 2_a is 1, keep value in 2_c, if not ignore
If 3_a is 1, keep value in 3_c, if not ignore

计算每行保留值的平均值,并将其存储在“ NEW”列中

我尝试了几种方法,但是只有在数据帧中只有1行的情况下它才有效。如果我有多于1行,似乎要计算整个数据帧的均值。 另外,由于我有10种以上的IF条件,因此我尝试优化功能。 那是我尝试过的方法,但是并没有给我结果,我在寻找:

 def test(x):
    a = x[x['1_a']==1]['1_c'].values
    b = x[x['2_a']==1]['2_c'].values
    c = x[x['3_a']==1]['3_c'].values
    xx =np.concatenate((a,b,c), axis=0)
    z = sum(xx)/len(xx)
    x['New_Prob'] = z
    return x
print(test(df))

结果是这样的:

ID, 1_a, 1_b, 1_c, 2_a, 2_b, 2_c, 3_a, 3_b, 3_c, NEW
0, 0, 145, 0.8, 0, 555, 0.7, 1, 335, 0.7, 0.6
1, 1, 222, 0.8, 1, 224, 0.4, 1, 555, 0.6, 0.6
3, 1, 111, 0.3, 0, 222, 0.5, 1, 999, 0.7, 0.6

3 个答案:

答案 0 :(得分:1)

您可以通过编写一个for loop来简化此过程,该列在每列中都带有后缀_c_a,并使用np.where有条件地用NaN替换值。

最后,您使用pandas.DataFrame.mean创建了NEW

# First we remove the spaces from your column names
df.columns = df.columns.str.strip()

amt_cols_check = 3

for x in range(amt_cols_check):
    df[f'{x+1}_c'] = np.where(df[f'{x+1}_a'] == 1, df[f'{x+1}_c'], np.NaN)

cols_mean = [col for col in df.columns if col.endswith('_c')]
df['NEW'] =  round(df[cols_mean].mean(axis=1), 1)

print(df)
   ID  1_a  1_b  1_c  2_a  2_b  2_c  3_a  3_b  3_c  NEW
0   0    0  145  NaN    0  555  NaN    1  335  0.7  0.7
1   1    1  222  0.9    1  224  0.4    1  555  0.6  0.6
2   3    1  111  0.3    0  222  NaN    1  999  0.7  0.5

注释,如AlexK在评论中指出的。我在答案中使用f-strings,只有Python 3.6和更高版本才支持。

答案 1 :(得分:0)

如果您的列在'_a'和'_c'的相似范围内,则只需遍历它们;

r = range(1,4)
for i in r:
    df.loc[df["{}_a".format(i)] != 1, "{}_c".format(i)] = np.NaN

df['NEW'] = df[['{}_c'.format(i) for i in r]].mean(axis=1)

答案 2 :(得分:0)

这里是一种解决方案,不需要用任何东西替换数据框中的现有值,而是假定“ _a”列中只有1和0。

这个问题实质上变成了“ _c”列的加权平均值,由“ _a”列加权。

df.columns = df.columns.str.strip()

a_cols = [col for col in df.columns if col.endswith('_a')]
c_cols = [col for col in df.columns if col.endswith('_c')]
#create a list of tuples of column names, i.e., [('1_a', '1_c'), ('2_a', '2_c'), ('3_a', '3_c')]
a_c = list(zip(a_cols,c_cols)) #if using Python 2.x, use zip(a_cols,c_cols)

df['NEW'] = sum([df[x] * df[y] for x,y in a_c]) / sum([df[z] for z in a_cols])