pandas有条件地选择多列

tzdcorbm  于 2023-03-28  发布在  其他
关注(0)|答案(5)|浏览(384)

假设我有一个 Dataframe :

C1 V1 C2 V2 Cond
1  2  3  4  X  
5  6  7  8  Y  
9  10 11 12 X

这些语句应返回:if Cond == X, pick C1 and v1, else pick C2 and V2
输出的dataframe类似于:

C  V 
1  2 
7  8
9  10

**编辑:添加一个要求:列的数量可以改变,但要遵循一些命名模式。在这种情况下,选择所有带有“1”的列,否则选择“2”。我认为硬编码的解决方案可能不起作用。

w1e3prcc

w1e3prcc1#

使用DataFrame.where()的另一个选项:

df[['C1', 'V1']].where(df.Cond == "X", df[['C2', 'V2']].values)

#  C1   V1
#0  1    2
#1  7    8
#2  9   10
yvgpqqbh

yvgpqqbh2#

我尝试使用filternumpy.where创建更通用的解决方案,对于新的列名使用extract

#if necessary sort columns
df = df.sort_index(axis=1)

#filter df by 1 and 2
df1 = df.filter(like='1')
df2 = df.filter(like='2')
print (df1)
   C1  V1
0   1   2
1   5   6
2   9  10

print (df2)
   C2  V2
0   3   4
1   7   8
2  11  12
#np.where need same shape of mask as df1 and df2
mask = pd.concat([df.Cond == 'X']*len(df1.columns), axis=1)
print (mask)
    Cond   Cond
0   True   True
1  False  False
2   True   True

cols = df1.columns.str.extract('([A-Za-z])', expand=False)
print (cols)
Index(['C', 'V'], dtype='object')

print (np.where(mask, df1,df2))
Index(['C', 'V'], dtype='object')
[[ 1  2]
 [ 7  8]
 [ 9 10]]

print (pd.DataFrame(np.where(mask, df1, df2), index=df.index, columns=cols))
   C   V
0  1   2
1  7   8
2  9  10
s3fp2yjn

s3fp2yjn3#

  • dropCond用于关注我从中选择的值
  • reshape numpy数组,所以我可以用布尔值区分
  • np.arange(len(df))索引第一个维度,每一行一次
  • df.Cond.ne('X').mul(1).0索引第二维,等于X
  • 构造最终 Dataframe
pd.DataFrame(
    df.drop('Cond', 1).values.reshape(3, 2, 2)[
        np.arange(len(df)),
        df.Cond.ne('X').mul(1)
    ], df.index, ['C', 'V'])

   C   V
0  1   2
1  7   8
2  9  10
rta7y2nd

rta7y2nd4#

如果行的顺序不重要,可以使用df.locdf.append

ndf1 = df.loc[df['Cond'] == 'X', ['C1','V1']]
ndf2 = df.loc[df['Cond'] == 'Y', ['C2','V2']]
ndf1.columns = ['C','V']
ndf2.columns = ['C','V']

result = ndf1.append(ndf2).reset_index(drop=True)
print(result)
   C   V
0  1   2
1  9  10
2  7   8
s5a0g9ez

s5a0g9ez5#

您可以尝试使用类似于this post中的方法
首先,定义几个函数:

def cond(row):
    return row['Cond'] == 'X'

def helper(row, col_if, col_ifnot):
    return row[col_if] if cond(row) else row[col_ifnot]

然后,假设您的 Dataframe 名为df

df_new = pd.DataFrame(index=df.index)
for col in ['C', 'V']:
    col_1 = col + '1'
    col_2 = col + '2'
    df_new[col] = df.apply(lambda row: helper(row, col_1, col_2), axis=1)

请记住,这种方法对于大型 Dataframe 可能会很慢,因为apply没有利用向量化。但是,它甚至可以用于任意列名(只需将['C', 'V']替换为实际列名)。

相关问题