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

Python 熊猫-根据其他列中的值计算具有条件的列的平均值,python,pandas,if-statement,iteration,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,

我努力在数据框中创建一个新的列,这将是在数据框中遍历每一行并根据某些条件计算平均值的结果。 这就是数据帧的外观

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”列中

我尝试了几种方法,但只有在数据帧中只有一行时才有效。如果我有超过一行,它似乎可以计算整个数据帧的平均值。 此外,我尝试优化功能,因为我有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

您可以通过为循环编写一个
来简化此过程,该循环使用后缀
\u c
\u a
遍历每一列,并使用有条件地将值替换为
NaN

最后,您可以使用


注意如AlexK在评论中所述。我在回答中使用了
f-strings
,只有Python 3.6和更高版本才支持它。

如果您的列在“\u a”和“\u 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)

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

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


为了让OP受益,我只想提到这个答案中使用的f字符串可以与Python3.6或更高版本一起使用。如果OP有一个早期版本,for循环可以遍历cols_mean列名列表,并将_c替换为_a。感谢Erfan的快速帮助!不过,我已经接受了最后一个答案,因为它看起来是我最整洁的方式。当然没问题,但基本上我的答案被改写了@约坦克斯!真管用!这看起来是一个简洁的答案。
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)
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])