Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aggregation on Pandas data frame for selected rows

Tags:

I have a pandas sorted data frame (based on time) like this:

from datetime import datetime
df = pd.DataFrame({ 'ActivityDateTime' : [datetime(2016,5,13,6,14),datetime(2016,5,13,6,16),
                                 datetime(2016,5,13,6,20),datetime(2016,5,13,6,27),datetime(2016,5,13,6,31),
                                 datetime(2016,5,13,6,32),
                                datetime(2016,5,13,17,34),datetime(2016,5,13,17,36),
                                 datetime(2016,5,13,17,38),datetime(2016,5,13,17,45),datetime(2016,5,13,17,47),
                                datetime(2016,5,16,13,3),datetime(2016,5,16,13,6),
                                 datetime(2016,5,16,13,10),datetime(2016,5,16,13,14),datetime(2016,5,16,13,16)],
              'Value1' : [0.0,2.0,3.0,4.0,0.0,0.0,0.0,7.0,8.0,4.0,0.0,0.0,3.0,9.0,1.0,0.0],
               'Value2' : [0.0,2.0,3.0,4.0,0.0,0.0,0.0,7.0,8.0,4.0,0.0,0.0,3.0,9.0,1.0,0.0]
        })

Which turns out like this:

ActivityDateTime    Value1  Value2
0   2016-05-13 06:14:00 0.0 0.0
1   2016-05-13 06:16:00 2.0 2.0
2   2016-05-13 06:20:00 3.0 3.0
3   2016-05-13 06:27:00 4.0 4.0
4   2016-05-13 06:31:00 0.0 0.0
5   2016-05-13 06:32:00 0.0 0.0
6   2016-05-13 17:34:00 0.0 0.0
7   2016-05-13 17:36:00 7.0 7.0
8   2016-05-13 17:38:00 8.0 8.0
9   2016-05-13 17:45:00 4.0 4.0
10  2016-05-13 17:47:00 0.0 0.0
11  2016-05-16 13:03:00 0.0 0.0
12  2016-05-16 13:06:00 3.0 3.0
13  2016-05-16 13:10:00 9.0 9.0
14  2016-05-16 13:14:00 1.0 1.0
15  2016-05-16 13:16:00 0.0 0.0

I'd like to aggregate the data (averaging) without a for loop. However, the way I am going to group the observations is not straight forward! Looking at Value1, I want to group them as non-zero values together. For example, indicies 1,2,3 would be in one group. Incidies 7,8,9 in one group and another one would be 12,13,14. The rows where value1==0, should be avoided and the zeros just act as a separation between groups. Eventually I'd like to get something like this:

Activity_end    Activity_start  Value1  Value2  num_observations
0   2016-05-13 06:27:00 2016-05-13 06:16:00 4.50    4.50    3
1   2016-05-13 17:45:00 2016-05-13 17:36:00 6.33    6.33    3
2   2016-05-16 13:14:00 2016-05-16 13:06:00 4.33    4.33    3

Currently, I am thinking that I should somehow assign numbers 1,2 and 3 to a new column and then aggregate them based on that. I am not sure how to make that column without a for loop though! Please notice that Value1 and Value2 are not necessarily the same.

like image 914
ahoosh Avatar asked May 13 '16 23:05

ahoosh


People also ask

How do you aggregate rows in a data frame?

Pandas DataFrame aggregate() MethodThe aggregate() method allows you to apply a function or a list of function names to be executed along one of the axis of the DataFrame, default 0, which is the index (row) axis. Note: the agg() method is an alias of the aggregate() method.

How do I filter specific rows from a DataFrame?

You can use df[df["Courses"] == 'Spark'] to filter rows by a condition in pandas DataFrame. Not that this expression returns a new DataFrame with selected rows. You can also write the above statement with a variable.

How do you get groupby rows in pandas?

You can group DataFrame rows into a list by using pandas. DataFrame. groupby() function on the column of interest, select the column you want as a list from group and then use Series. apply(list) to get the list for every group.


1 Answers

One way of doing it involves creating some temporary columns

# First create a new series, which is true whenever the value changes from a zero value to a non-zero value (which will be at the start of each group)
nonzero = (df['Value1'] > 0) & (df['Value1'].shift(1) == 0)
# Take a cumulative sum. This means each group will have it's own number.
df['group'] = df['nonzero'].cumsum()
# Group by the group column
gb = df[df['Value1'] > 0].groupby('group')

You can then take aggregates of this group using the aggregate functions http://pandas.pydata.org/pandas-docs/stable/groupby.html

For what you're specifically wanting to get as an output, have a look at this answer too: Python Pandas: Multiple aggregations of the same column

df2 = gb.agg({
    'ActivityDateTime': ['first', 'last'],
    'Value1': 'mean',
    'Value2': 'mean'})
like image 192
Jezzamon Avatar answered Oct 06 '22 00:10

Jezzamon