根据其他列的值生成新列。

3

这是我的样例数据输入和输出:

df=pd.DataFrame({'A_flag': [1, 1,1], 'B_flag': [1, 1,0],'C_flag': [0, 1,0],'A_value': [5, 3,7], 'B_value': [2, 7,4],'C_value': [4, 2,5]})

df1=pd.DataFrame({'A_flag': [1, 1,1], 'B_flag': [1, 1,0],'C_flag': [0, 1,0],'A_value': [5, 3,7], 'B_value': [2, 7,4],'C_value': [4, 2,5], 'Final':[3.5,3,7]})


我想基于A_flag、B_flag和C_flag生成另一列"Final":
(a) 如果这三个列中为1的数量等于3,则 'Final' 等于 (A_value, B_value, C_value) 的中位数
(b) 如果满足条件的数量为2,则 'Final' 等于这两个数的平均值
(c) 如果数量为1,则 'Final' = 这个数
例如,在第1行,A_flag=1且B_flag=1,则 'Final'=A_value+B_value/2=5+2/2=3.5 ;在第2行中,所有三个标志都是1,所以 'Final'= (3,7,2) 的中位数=3 ;在第3行中,只有 A_flag=1,则 'Final'= A_value=7。
我尝试了以下代码:
df.loc[df[['A_flag','B_flag','C_flag']].eq(1).sum(axis=1)==3, "Final"]= df[['A_flag','B_flag','C_flag']].median(axis=1)

df.loc[df[['A_flag','B_flag','C_flag']].eq(1).sum(axis=1)==2, "Final"]=
df.loc[df[['A_flag','B_flag','C_flag']].eq(1).sum(axis=1)==1, "Final"]=  

我不知道如何对第二个和第三个场景进行列子集。

4个回答

3
假设标志和值列的顺序匹配,您可以首先过滤类似于标志和值的列,然后将mask应用于value列中flag0的值,最后沿axis=1计算median
flag = df.filter(like='_flag')
value = df.filter(like='_value')

df['median'] = value.mask(flag.eq(0).to_numpy()).median(1)

   A_flag  B_flag  C_flag  A_value  B_value  C_value  median
0       1       1       0        5        2        4     3.5
1       1       1       1        3        7        2     3.0
2       1       0       0        7        4        5     7.0

不错的技巧。我忽略了当只有两个值时,平均数=中位数。 - Code Different
谢谢!这是一个有趣的解决方案。所以这适用于特定的例子,比如说如果我有4个标志,并且只有3个标志=1时需要计算平均值,在这种情况下,我不能使用技巧mean=median来处理我这里的特殊情况,对吗? - Derek

1

处理函数和数据框时,通常最简单的方法是定义一个函数,然后通过迭代列或行来调用该函数到数据框中。我认为在您的情况下,这可能会起作用:

import pandas as pd

df = pd.DataFrame(
    {
        "A_flag": [1, 1, 1],
        "B_flag": [1, 1, 0],
        "C_flag": [0, 1, 0],
        "A_value": [5, 3, 7],
        "B_value": [2, 7, 4],
        "C_value": [4, 2, 5],
    }
)

def make_final_column(row):
    flags = [(row['A_flag'], row['A_value']), (row['B_flag'], row['B_value']), (row['C_flag'], row['C_value'])]
    met_condition = [row[1] for row in flags if row[0] == 1]
    return sum(met_condition) / len(met_condition)


df["Final"] = df.apply(make_final_column, axis=1)
df

1

使用NumPy:

flags = df[["A_flag", "B_flag", "C_flag"]].to_numpy()
values = df[["A_value", "B_value", "C_value"]].to_numpy()

# Sort each row so that the 0 flags appear first
index = np.argsort(flags)
flags = np.take_along_axis(flags, index, axis=1)
# Rearrange the values to match the flags
values = np.take_along_axis(values, index, axis=1)

# Result
np.select(
    [
        flags[:, 0] == 1, # when all flags are 1
        flags[:, 1] == 1, # when two flags are 1
        flags[:, 2] == 1, # when one flag is 1
    ],
    [
        np.quantile(values, 0.5, axis=1), # median all of 3 values
        np.mean(values[:, -2:], axis=1),  # mean of the two 1-flag
        values[:, 2],                     # value of the 1-flag
    ],
    default=np.nan
)

0

已经有相当有趣的解决方案了。我使用了遮罩方法。

说明: 因此,通过给定的标志,可以通过乘以该标志来轻松找到哪些值是重要的。然后,在各自的行中掩盖为零的值,并在轴上找到中位数。

>>> import numpy as np 
>>> t_arr = np.array((df.A_flag * df.A_value, df.B_flag * df.B_value, df.C_flag * df.C_value)).T

>>> maskArr = np.ma.masked_array(t_arr, mask=x==0) 

>>> df["Final"] = np.ma.median(maskArr, axis=1)

>>> df

A_flag  B_flag  C_flag  A_value     B_value     C_value     Final
0   1     1       0       5           2           4          3.5
1   1     1       1       3           7           2          3.0
2   1     0       0       7           4           5          7.0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接