【问题标题】:Splitting a Column on Positive and Negative values根据正值和负值拆分列
【发布时间】:2017-04-13 12:12:32
【问题描述】:

如何根据条件将一列拆分为两个不同的列,但保留一个键?例如

      col1  col2   time       value
0      A     sdf  16:00:00     100
1      B     sdh  17:00:00     -40
2      A     sf   18:00:45     300 
3      D     sfd  20:04:33     -89

我想要一个这样的新数据框

     time       main_val    sub_val
0   16:00:00     100         NaN
1   17:00:00     NaN         -40
2   18:00:45     300         NaN
3   20:04:33     NaN         -89

【问题讨论】:

    标签: python pandas numpy dataframe


    【解决方案1】:

    你可以使用mask:

    mask = df['value'] < 0
    df['main_val'] = df['value'].mask(mask)
    df['sub_val'] = df['value'].mask(~mask)
    df = df.drop(['col1','col2', 'value'], axis=1)
    print (df)
           time  main_val  sub_val
    0  16:00:00     100.0      NaN
    1  17:00:00       NaN    -40.0
    2  18:00:45     300.0      NaN
    3  20:04:33       NaN    -89.0
    

    【讨论】:

    • @MaxU - 谢谢。
    【解决方案2】:

    我使用pd.get_dummiesmaskmul

    n = {True: 'main_val', False: 'sub_val'}
    m = pd.get_dummies(df.value > 0).rename(columns=n)
    df.drop('value', 1).join(m.mask(m == 0).mul(df.value, 0))
    
      col1 col2      time  sub_val  main_val
    0    A  sdf  16:00:00      NaN     100.0
    1    B  sdh  17:00:00    -40.0       NaN
    2    A   sf  18:00:45      NaN     300.0
    3    D  sfd  20:04:33    -89.0       NaN
    

    如果您查看m.mask(m == 0),就会更清楚这是如何工作的。

       sub_val  main_val
    0      NaN       1.0
    1      1.0       NaN
    2      NaN       1.0
    3      1.0       NaN
    

    pd.get_dummies 给了我们零和一。然后我把所有的零都变成np.nan。当我与mul 相乘时,df.value 列会在这两个列中广播,我们就有了结果。我使用join 将其附加回数据框。


    我们可以通过numpy提高速度

    v = df.value.values[:, None]
    m = v > 0
    n = np.where(np.hstack([m, ~m]), v, np.nan)
    c = ['main_val', 'sub_val']
    df.drop('value', 1).join(pd.DataFrame(n, df.index, c))
    
       sub_val  main_val
    0      NaN       1.0
    1      1.0       NaN
    2      NaN       1.0
    3      1.0       NaN
    

    【讨论】:

      【解决方案3】:

      这甚至可以通过数据透视表来完成

      df['Val1'] = np.where(df.value >=0,'main_val','sub_val' )
      
      df = pd.pivot_table(df,index='time', values='value',
                      columns=['Val1'], aggfunc=np.sum).reset_index()
      
      df = pd.DataFrame(df.values)
      df.columns = ['time','main_val','sub_val']
      

      【讨论】:

        【解决方案4】:

        使用DataFrame.where

        import pandas as pd
        df = pd.DataFrame({'col1':['A', 'B', 'A', 'D'],
                           'col2':['sdf', 'sdh', 'sf', 'sfd'],
                           'time':['16:00:00', '17:00:00', '18:00:45', '20:04:33'],
                           'value':[100, -40, 300, -89]})
        print(df)
        
          col1 col2      time  value
        0    A  sdf  16:00:00    100
        1    B  sdh  17:00:00    -40
        2    A   sf  18:00:45    300
        3    D  sfd  20:04:33    -89
        

        .

        new = df[['time']].copy()
        new['main_val'] = df['value'].where(df['value'] > 0)
        new['sub_val'] = df['value'].where(df['value'] < 0)
        print(new)
        
               time  main_val  sub_val
        0  16:00:00     100.0      NaN
        1  17:00:00       NaN    -40.0
        2  18:00:45     300.0      NaN
        3  20:04:33       NaN    -89.0
        

        【讨论】:

          【解决方案5】:

          你需要df.assignnp.where

          mask=df['value'] < 0
          df=df.assign(max_value=(np.where(mask,df['value'],np.nan)),min_value=(np.where(~mask,df['value'],np.nan)))
          
          df=df[['time','max_value','min_value']]
          

          【讨论】:

            【解决方案6】:

            在创建新列以从 nans 或列值中选择时使用 numpy where(比 df.where 稍快,灵感来自 Kamaraju Kusumanchi 的出色回答)

            vals = df.value.values
            nans = np.full(len(df), np.nan)
            df2 = df[['time']].copy()
            df2['main_val'] = np.where(vals < 0, nans, vals)
            df2['sub_val'] = np.where(vals >= 0, nans, vals)
            
            print(df2)
            
                   time  main_val  sub_val
            0  16:00:00     100.0      NaN
            1  17:00:00       NaN    -40.0
            2  18:00:45     300.0      NaN
            3  20:04:33       NaN    -89.0
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-01-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-05-29
              • 2021-07-12
              • 1970-01-01
              相关资源
              最近更新 更多