简体   繁体   中英

get min and max values of several values in a df

I have this df :

df=pd.DataFrame({'stop_i':['stop_0','stop_0','stop_0','stop_1','stop_1','stop_0','stop_0'],'time':[0,10,15,50,60,195,205]})

Each line corresponds to the time (in seconds) where the bus was at the stop_i .

First, i want to count how much times the bus was at stop_i with 180 seconds between the last seen and the next one first seen. The result would be {'stop_0' : 2,'stop_1': 1} because for stop_0 the last time it has been seen for the first time was at 15s then its appears again at 195s so 195-15<=180 then it counts for 2 and stop_1 appears only one time

Secondly I want to get this dict : {'stop_0' : [[0,15],[195,205], 'stop_1': [[50,60]]} containing the min and the max value of the time when the bus was at the stop_i

Is there a way to do that with pandas to avoid a loop through the df ?

Thanks !

No looping

  1. generate a new column that is the set of times that bus is at a stop (assumes index is sequential)
  2. from this get first and last times. then construct a list of first / last times. Plus calcs for > 180s. This logic seems odd. stop_1 only has one visit so count of 1 for > 180s is forced
  3. finally get dictionaries you want.
df=pd.DataFrame({'stop_i':['stop_0','stop_0','stop_0','stop_1','stop_1','stop_0','stop_0'],'time':[0,10,15,50,60,195,205]})

dfp =(df
      # group when a bus is at a stop
 .assign(
    grp=lambda dfa: np.where(dfa["stop_i"].shift()!=dfa["stop_i"], dfa.index, np.nan)
)
 .assign(
     grp=lambda dfa: dfa["grp"].fillna(method="ffill")
 )
      # within group get fisrt and last time it's at stop
 .groupby(["stop_i","grp"]).agg({"time":["first","last"]})
 .reset_index()
      # based on expected output... in reality there is only 1 time bus is between stops
      # > 180 seconds.  stop_1 only has one visit to cannot be > 180s
 .assign(
     combi=lambda dfa: dfa.apply(lambda r: [r[("time","first")], r[("time","last")]] , axis=1),
     stopchng=lambda dfa: dfa[("stop_i")]!=dfa[("stop_i")].shift(),
     timediff=lambda dfa: dfa[("time","first")] - dfa[("time","last")].shift(),
     
 )
)

# first requirement... which seems wrong
d1 = (dfp.loc[(dfp[("timediff")]>=180) | dfp[("stopchng")], ]
     .groupby("stop_i")["stop_i"].count()
     .to_frame().T.reset_index(drop="True")
     .to_dict(orient="records")
)


# second requirement
d2 = (dfp.groupby("stop_i")["combi"].agg(lambda s: list(s))
      .to_frame().T.reset_index(drop=True)
      .to_dict(orient="records")
     )

print(d1, d2)

output

[{'stop_0': 2, 'stop_1': 1}] [{'stop_0': [[0, 15], [195, 205]], 'stop_1': [[50, 60]]}]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM