根据另一列的存在删除一列

Drop a column based on the existence of another column

我实际上是想弄清楚如何根据另一列的存在删除一列。这是我的问题:

我从这个 DataFrame 开始。每个“X”列都使用一个数字与一个“Y”列相关联。 (X_1,Y_1 / X_2,Y_2 ...)

  Index X_1 X_2 Y_1  Y_2                
    1    4   0   A   NaN
    2    7   0   A   NaN
    3    6   0   B   NaN
    4    2   0   B   NaN
    5    8   0   A   NaN

我使用 pd.dropna() 删除 NaN 值。我得到的结果是这个 DataFrame :

  Index X_1 X_2 Y_1             
    1    4   0   A   
    2    7   0   A
    3    6   0   B
    4    2   0   B
    5    8   0   A

问题是我想删除与刚刚删除的“Y”列关联的“X”列。我想使用基本上说的条件:

“如果 Y_2 不在 DataFrame 中,则删除 X_2 列”

我使用了 for 循环组合到 if,但它似乎不起作用。有什么想法吗?

谢谢,祝你有美好的一天。

  1. 删除 nas

    df.dropna(轴=1,就地=真)

  2. 计算后缀和包含两个后缀的列

    后缀 = [i[2:] for i in df.columns cols = [c for c in df.columns if suffixes.count(c[2:]) == 2]

  3. 过滤列

    df[列]

完整代码:

df = df.set_index('Index').dropna(axis=1)
suffixes = [i[2:] for i in df2.columns]
df[[c for c in df2.columns if suffixes.count(c[2:]) == 2]]

稍微修改示例以更接近实际 DataFrame:

df = pd.DataFrame({
    'Index': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5},
    'X_V1_C': {0: 4, 1: 7, 2: 6, 3: 2, 4: 8},
    'X_V2_C': {0: 0, 1: 0, 2: 0, 3: 0, 4: 0},
    'Y_V1_C': {0: 'A', 1: 'A', 2: 'B', 3: 'B', 4: 'A'},
    'Y_V2_C': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan}
})
   Index  X_V1_C  X_V2_C Y_V1_C  Y_V2_C
0      1       4       0      A     NaN
1      2       7       0      A     NaN
2      3       6       0      B     NaN
3      4       2       0      B     NaN
4      5       8       0      A     NaN
  1. set_index 在要“保存”的任何列上
  2. Extract 列中的数字并创建一个 MultiIndex
df.columns = pd.MultiIndex.from_arrays([df.columns.str.extract(r'(\d+)')[0],
                                        df.columns])

0          1      2      1      2  # Numbers Extracted From Columns
      X_V1_C X_V2_C Y_V1_C Y_V2_C
Index                            
1          4      0      A    NaN
2          7      0      A    NaN
3          6      0      B    NaN
4          2      0      B    NaN
5          8      0      A    NaN
  1. 检查哪里有所有 NaN 列的组 DataFrame.isna all on axis=0 (columns) then any 相对于 level=0(提取的数字)
col_mask = ~df.isna().all(axis=0).any(level=0)

0
1     True  # Keep 1 Group
2    False  # Don't Keep 2 Group
dtype: bool

4.filter 带有掩码的 DataFrame 在添加的数字级别上使用 loc then droplevel

df = df.loc[:, col_mask.index[col_mask]].droplevel(axis=1, level=0)

       X_V1_C Y_V1_C
Index               
1           4      A
2           7      A
3           6      B
4           2      B
5           8      A

齐心协力

df = df.set_index('Index')

df.columns = pd.MultiIndex.from_arrays([df.columns.str.extract(r'(\d+)')[0],
                                        df.columns])
col_mask = ~df.isna().all(axis=0).any(level=0)
df = df.loc[:, col_mask.index[col_mask]].droplevel(axis=1, level=0)

df:

       X_V1_C Y_V1_C
Index               
1           4      A
2           7      A
3           6      B
4           2      B
5           8      A

设置

>>> df

       CHA_COEXPM1_COR  CHA_COEXPM2_COR CHA_COFMAT1_COR  CHA_COFMAT2_COR
Index                                                                   
1                    4                0               A              NaN
2                    7                0               A              NaN
3                    6                0               B              NaN
4                    2                0               B              NaN
5                    8                0               A              NaN

解决方案

  • 识别任何行中具有 NaN 个值的列
  • 使用数字标识符对标识的列进行分组,transform 使用 any
  • 使用在上一步中创建的布尔掩码过滤列
m = df.isna().any()
m = m.groupby(m.index.str.extract(r'(\d+)_')[0]).transform('any')

结果

>>> df.loc[:, ~m]

       CHA_COEXPM1_COR CHA_COFMAT1_COR
Index                                 
1                    4               A
2                    7               A
3                    6               B
4                    2               B
5                    8               A