0
$\begingroup$

Good morning everyone.

I have the following data:

import pandas as pd

info = {
'states': [-1, -1, -1, 1, 1, -1, 0, 1, 1, 1],
'values': [34, 29, 28, 30, 35, 33, 33, 36, 40, 41] }

df = pd.DataFrame(data=info)

print(df)

>>> 
    states   values
0       -1       34
1       -1       29
2       -1       28
3        1       30
4        1       35
5       -1       33
6        0       33
7        1       36
8        1       40
9        1       41

I need to group the data using PANDAS (and/or higher order functions) (already did the exercise using for loops), I need to group the data having the "states" column as a guide. But the grouping should not be of all the data, I only need to group the data that is neighboring... as follows:

Initial DataFrame:

    states   values
0       -1       34 ┐
1       -1       29 │    Group this part (states = -1)
2       -1       28 ┘
3        1       30 ┐    Group this part (states =  1)
4        1       35 ┘
5       -1       33     'Group' this part (states = -1)
6        0       33     'Group' this part (states =  0)
7        1       36 ┐
8        1       40 │    Group this part (states =  1)
9        1       41 ┘

It would result in a DataFrame, with a grouping by segments (from the "states" column) and in another column the sum of the data (from the "values" column).

Expected DataFrame:

    states   values
0       -1       91     (values=34+29+28)
1        1       65     (values=30+35)
2       -1       33
3        0       33
4        1       117    (values=36+40+41)

You who are more versed in these issues, perhaps you can help me perform this operation.

Thank you so much!

$\endgroup$

2 Answers 2

1
$\begingroup$

You can do this by making use of shift to create different groups based on consecutive values of the states column, after which you can use groupby to add the values in the values column:

(
    df
    .assign(
        # create groups by checking if value is different from previous value
        group = lambda x: (x["states"] != x["states"].shift()).cumsum()
    )
    # group by the states and group columns
    .groupby(["states", "group"])
    # sum the values in the values column
    .agg({"values": "sum"})
    .reset_index()
    # select the columns needed in the final output
    .loc[:, ["group", "values"]]
)
$\endgroup$
1
  • $\begingroup$ Oxbowerce thank you very much, Your answer is just what I was looking for. $\endgroup$ Mar 4, 2023 at 19:00
0
$\begingroup$

enter image description here

It's not the problem about grouping the elements, it is the problem related to consecutive elements. The approach should be of using consecutive iterations.

Here I've saved all the results in a list. Don't use any dictionary to store results as its key values should be unique.

enter image description here

Your desired output ☝️

$\endgroup$
2
  • 1
    $\begingroup$ It would help if you could post the code you used as a code block instead of image, as it makes it easier for others to copy and try out. $\endgroup$
    – Oxbowerce
    Mar 4, 2023 at 16:27
  • $\begingroup$ Pragyan Tiwari, Thank you very much for your time and your answer... $\endgroup$ Mar 4, 2023 at 19:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.