Search code examples
pythonpandasdataframedifference

Dataframe - difference of rows by some style


I want the difference of column 'position' by the column 'Seg' with 'x' adjacent.

import numpy as np
import pandas as pd
mydict = {'position':['0.0', '0.433', '2.013', '3.593', '5.173', '6.753', '6.9'],'Seg':['x', 'x', np.nan, np.nan, np.nan, np.nan, 'x']}
df = pd.DataFrame.from_dict(mydict)
df

   position  Seg
0      0.0    x
1    0.433    x
2    2.013  NaN
3    3.593  NaN
4    5.173  NaN
5    6.753  NaN
6      6.9    x

How can I get the difference 'diff' and 'Seg ID'? Note: 'x' can randomly be at any rows and 'Seg ID' changes accordingly.

   position  Seg   diff  Seg ID
0      0.0    x     NaN    NaN
1    0.433    x   0.433  Seg 1
2    2.013  NaN    NaN    NaN
3    3.593  NaN    NaN    NaN
4    5.173  NaN    NaN    NaN
5    6.753  NaN    NaN    NaN
6      6.9    x   6.467  Seg 2

Solution

  • Convert strings in position to float by Series.astype first:

    df['position'] = df['position'].astype(float)
    

    Get differencies by Series.diff by mask - compare by x:

    m = df['Seg'].eq('x')
    df.loc[m, 'diff'] = df.loc[m, 'position'].diff()
    

    Create counter if difference is not NaN by Series.cumsum:

    m1 = df['diff'].notna()
    df.loc[m1, 'Seg ID'] = 'Seg ' + m1[m1].cumsum().astype(str)
    print (df)
       position  Seg   diff Seg ID
    0     0.000    x    NaN    NaN
    1     0.433    x  0.433  Seg 1
    2     2.013  NaN    NaN    NaN
    3     3.593  NaN    NaN    NaN
    4     5.173  NaN    NaN    NaN
    5     6.753  NaN    NaN    NaN
    6     6.900    x  6.467  Seg 2
    

    Different input data:

    mydict = {'position':['0.0', '0.433', '2.013', '3.593', '5.173', '6.753', '6.9'],
              'Seg':['x', 'x', np.nan, np.nan, np.nan, 'x', 'x']}
    df = pd.DataFrame.from_dict(mydict)
    print (df)
      position  Seg
    0      0.0    x
    1    0.433    x
    2    2.013  NaN
    3    3.593  NaN
    4    5.173  NaN
    5    6.753    x
    6      6.9    x
    
    df['position'] = df['position'].astype(float)
    m = df['Seg'].eq('x')
    df.loc[m, 'diff'] = df.loc[m, 'position'].diff()
    
    m1 = df['diff'].notna()
    df.loc[m1, 'Seg ID'] = 'Seg ' + m1[m1].cumsum().astype(str)
    
    print (df)
       position  Seg   diff Seg ID
    0     0.000    x    NaN    NaN
    1     0.433    x  0.433  Seg 1
    2     2.013  NaN    NaN    NaN
    3     3.593  NaN    NaN    NaN
    4     5.173  NaN    NaN    NaN
    5     6.753    x  6.320  Seg 2
    6     6.900    x  0.147  Seg 3