【问题标题】:Transpose based on column values基于列值转置
【发布时间】:2021-07-02 00:42:02
【问题描述】:

我有一个包含汽车及其颜色的数据框:

colors_df = pd.DataFrame({'id' : [1,2,3], 'Color_Red':[0,1,0],'Color_Blue':[1,0,0],'Color_Green':[1,1,1]})

| id | Color_Red | Color_Blue | Color_Green |
| 1  |.    0.    |     1      |      1      |
| 2  |.    1.    |     0      |      1      |  
| 3  |.    0.    |     0      |      1      |

我想为每个名为 Color_XXX_Only 的颜色创建一个额外的列,如果 id 的颜色中只有一个 1,则将其设置为值 1,如果它有多个颜色设置为 1,则另外设置一个 MultiColor 列。 预期输出:

| id | Color_Red | Color_Blue | Color_Green |   Only_Red | Only_Blue | Only_Green | MultiColor|
| 1  |.    0.    |     1      |      1      |.     0.    |      0    |    0       |       1.  |      
| 2  |.    1.    |     0      |      1      |.     0.    |      0    |    0       |       1.  |  
| 3  |.    0.    |     0      |      1      |.     0.    |      0    |    1       |       0   |

1 是多色的,因为它是蓝色和绿色的。

2 是多色的,因为它是红色和绿色的。

3 是 Onlye_blue 和多色,因为它只有绿色。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    一种方法(假设每个 id 包含在单行中并且不跨越多行)是计算每行 1 的数量:

    1. filter 仅获取 Color_
    2. sum 跨行得到 1s 的总数,然后与 gt 1 进行比较(直觉是具有多个 1 值的行是多色的)。
    colors_cols = colors_df.filter(like='Color_')
    multi_color = colors_cols.sum(axis=1).gt(1)
    

    multi_color:

    0     True
    1     True
    2    False
    dtype: bool
    

    屏蔽多色行并更新列名:

    1. mask 为 MultiColor 的行并将值设置为 0
    2. str.replace 更新列名,用Only_ 替换单词Color_
    colors_cols = colors_cols.mask(multi_color, 0)
    colors_cols.columns = (
        colors_cols.columns.str.replace(r'Color_(.*)', r'Only_\1', regex=True)
    )
    
       Only_Red  Only_Blue  Only_Green
    0         0          0           0
    1         0          0           0
    2         0          0           1
    

    然后join返回并添加多色列:

    1. join 将上述数据框返回到 colors_df 以添加 3 个新列。
    2. 转动multi_color,表示从boolint 的多色行与astype
    colors_df = colors_df.join(colors_cols)
    colors_df['MultiColor'] = multi_color.astype(int)
    

    colors_df:

       id  Color_Red  Color_Blue  Color_Green  Only_Red  Only_Blue  Only_Green  MultiColor
    0   1          0           1            1         0          0           0           1
    1   2          1           0            1         0          0           0           1
    2   3          0           0            1         0          0           1           0
    

    完整的工作示例:

    import pandas as pd
    
    colors_df = pd.DataFrame({
        'id': [1, 2, 3],
        'Color_Red': [0, 1, 0],
        'Color_Blue': [1, 0, 0],
        'Color_Green': [1, 1, 1]
    })
    
    # Create Necessary Boolean Information
    colors_cols = colors_df.filter(like='Color_')
    multi_color = colors_cols.sum(axis=1).gt(1)
    
    # Build Only_ columns
    colors_cols = colors_cols.mask(multi_color, 0)
    colors_cols.columns = (
        colors_cols.columns.str.replace(r'Color_(.*)', r'Only_\1', regex=True)
    )
    
    # Add Columns to `colors_df`
    colors_df = colors_df.join(colors_cols)
    colors_df['MultiColor'] = multi_color.astype(int)
    
    # Display
    print(colors_df.to_string())
    

    【讨论】:

    • 感谢您的回答!非常可靠,一个快速的问题,如果我想在列中添加修复前缀而不是替换列而不是 str.replace,我该怎么办?
    • 尝试colors_cols = colors_cols.mask(multi_color, 0).add_prefix('Something_'),然后删除colors_cols.columns = ... 部分
    【解决方案2】:

    这种方法使用掩码和位置

    #build masks
    m_red=(colors_df.Color_Red==1)
    m_blue=(colors_df.Color_Blue==1)
    m_green=(colors_df.Color_Green==1)
    m_multi=(colors_df.Color_Red+colors_df.Color_Blue+colors_df.Color_Green>1)
    
    #build new columns using loc
    colors_df.loc[m_red,'Only_Red']=1
    colors_df.loc[m_blue,'Only_Blue']=1
    colors_df.loc[m_green,'Only_Green']=1
    colors_df.loc[m_multi,'Multi']=1
    
    #use fillna to replace NaN with 0
    colors_df.fillna(0)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-26
      • 1970-01-01
      相关资源
      最近更新 更多