【问题标题】:How to subtract rows in a df based on a value in another column如何根据另一列中的值减去df中的行
【发布时间】:2018-10-12 03:36:02
【问题描述】:

我正在尝试根据其他列的值计算某些行中的差异。

使用下面的示例数据框,我想根据Code 列中的值计算Time 的差异。具体来说,我想循环并确定BA 之间的时间差。所以 B 中的时间 - A 中的时间。

我可以使用iloc 函数手动执行此操作,但我希望确定一种更有效的方法。特别是如果我必须多次重复这个过程。

import pandas as pd
import numpy as np

k = 5
N = 15

d = ({'Time' : np.random.randint(k, k + 100 , size=N),
    'Code' : ['A','x','B','x','A','x','B','x','A','x','B','x','A','x','B']})

df = pd.DataFrame(data=d)

输出:

   Code  Time
0     A    89
1     x    39
2     B    24
3     x    62
4     A    83
5     x    57
6     B    69
7     x    10
8     A    87
9     x    62
10    B    86
11    x    11
12    A    54
13    x    44
14    B    71

预期输出:

     diff
1    -65
2    -14
3    -1
4     17

【问题讨论】:

    标签: python pandas loops


    【解决方案1】:

    首先按boolean indexing 过滤,然后用reset_index 减去reset_index 作为对齐系列ab 的默认索引,最后如果想要一列DataFrame 添加to_frame

    a = df.loc[df['Code'] == 'A', 'Time'].reset_index(drop=True)
    b = df.loc[df['Code'] == 'B', 'Time'].reset_index(drop=True)
    

    类似的替代解决方案:

    a = df.loc[df['Code'] == 'A'].reset_index()['Time']
    b = df.loc[df['Code'] == 'B'].reset_index()['Time']
    

    c = b.sub(a).to_frame('diff')
    print (c)
       diff
    0   -65
    1   -14
    2    -1
    3    17
    

    新索引的最后一个从1开始添加rename

    c = b.sub(a).to_frame('diff').rename(lambda x: x + 1)
    print (c)
       diff
    1   -65
    2   -14
    3    -1
    4    17
    

    如果需要计算更多差异,另一种方法是通过unstack 重塑:

    df = df.set_index(['Code', df.groupby('Code').cumcount() + 1])['Time'].unstack()
    print (df)
             1     2     3     4     5     6     7
    Code                                          
    A     89.0  83.0  87.0  54.0   NaN   NaN   NaN
    B     24.0  69.0  86.0  71.0   NaN   NaN   NaN
    x     39.0  62.0  57.0  10.0  62.0  11.0  44.0
    

    #last remove `NaN`s rows
    c = df.loc['B'].sub(df.loc['A']).dropna()
    print (c)
    1   -65.0
    2   -14.0
    3    -1.0
    4    17.0
    dtype: float64
    
    #subtract with NaNs values - fill_value=0 return non NaNs values
    d = df.loc['x'].sub(df.loc['A'], fill_value=0)
    print (d)
    1   -50.0
    2   -21.0
    3   -30.0
    4   -44.0
    5    62.0
    6    11.0
    7    44.0
    dtype: float64
    

    【讨论】:

      【解决方案2】:

      假设您的Code'A', 'x', 'B', 'x' 的重复,您可以使用

      >>> (df.Time[df.Code == 'B'].reset_index() - df.Time[df.Code == 'A'].reset_index())[['Time']]
          Time
      0   -65
      1   -14
      2   -1
      3   17
      

      但请注意,最初的假设,即 'A''B' 值交替出现,似乎很脆弱。

      如果您希望索引从 1 运行到 4,就像您的问题一样,您可以将前一个分配给 diff,然后使用

      diff.index += 1
      >>> diff
          Time
      1   -65
      2   -14
      3   -1
      4   17
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-22
        • 2020-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多