Python 可以有条件地选择多个列

Python 可以有条件地选择多个列,python,pandas,conditional,extract,multiple-columns,Python,Pandas,Conditional,Extract,Multiple Columns,假设我有一个数据帧: C1 V1 C2 V2 Cond 1 2 3 4 X 5 6 7 8 Y 9 10 11 12 X 语句应该返回:如果Cond==X,选择C1和C2,否则选择C2和V2 输出数据帧类似于: C V 1 2 7 8 9 10 **编辑:再添加一个要求:列的数量可以更改,但遵循某种命名模式。在这种情况下,选择所有包含“1”的列,否则选择包含“2”的列。我认为硬编码的解决方案可能不起作用 dropCond关注我从中选择的值 重塑nump

假设我有一个数据帧:

C1 V1 C2 V2 Cond
1  2  3  4  X  
5  6  7  8  Y  
9  10 11 12 X
语句应该返回:
如果Cond==X,选择C1和C2,否则选择C2和V2

输出数据帧类似于:

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

  • drop
    Cond
    关注我从中选择的值
  • 重塑
    numpy数组,以便使用布尔值进行区分
  • np.arange(len(df))
    索引第一维度,每行一次
  • df.Cond.ne('X').mul(1)
    索引第二维度<代码>0表示等于
    X
  • 构造最终数据帧

  • drop
    Cond
    关注我从中选择的值
  • 重塑
    numpy数组,以便使用布尔值进行区分
  • np.arange(len(df))
    索引第一维度,每行一次
  • df.Cond.ne('X').mul(1)
    索引第二维度<代码>0表示等于
    X
  • 构造最终数据帧


您可以尝试使用与中类似的方法

首先,定义两个函数:

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]
然后,假设您的数据帧被称为
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)

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

您可以尝试使用与中类似的方法

首先,定义两个函数:

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]
然后,假设您的数据帧被称为
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)
请记住,这种方法对于大型数据帧可能比较慢,因为
apply
没有利用矢量化。但是,它甚至可以用于任意列名(只需将
['C','V']
替换为实际的列名即可)。

如果行的顺序不重要,则可以使用

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
如果行的顺序不重要,可以使用和

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

另一个带有
数据帧的选项。其中()


另一个带有
数据帧的选项。其中()


我尝试使用和创建更通用的解决方案,对于新列名,请使用:


我尝试使用和创建更通用的解决方案,对于新列名,请使用:


indexer={'X':['C1','V1'],'Y':['C2','V2']}的可能重复项;indexer.items()中k,v的pd.concat([pd.DataFrame(df.loc[df.Cond==k,v]。值,列=['C','v'])
是这样做的一种方法,但它不保留行的顺序。
indexer={'X':['C1',V1'],'Y':['C2',V2'];index.items()]中k,v的pd.concat([pd.DataFrame(df.loc[df.Cond==k,v]。值,列=['C','v'])
是一种方法,但它不保留行的顺序。
#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