I have this pd.Series
:
s = pd.Series([1, 'a', 1.4, 'b', 4, 98, 6.7, 'hello', 98.9])
My goal is to switch the values by each value type in reverse order.
My desired output is:
>>> s = pd.Series([98, 'hello', 98.9, 'b', 4, 1, 6.7, 'a', 1.4])
>>> s
0 98
1 hello
2 98.9
3 b
4 4
5 1
6 6.7
7 a
8 1.4
dtype: object
>>>
As you can see, the different value types are still in mixed order, but they are reversed by the other same type values.
The integer order was
1, 4, 98
and it's now98, 4, 1
.The float order was
1.4, 6.7, 98.9
and it's now98.9, 6.7, 1.4
.The string order was
'a', 'b', 'hello'
and it's now'hello', 'b', 'a'
What I have tried so far is:
>>> s.to_frame().groupby([[*map(type, s)]], sort=False).apply(lambda x: x.iloc[::-1]).reset_index(drop=True)
0
0 98
1 4
2 1
3 hello
4 b
5 a
6 98.9
7 6.7
8 1.4
>>>
And yes, they do get reversed in order. But, since I'm using groupby
, the values are grouped together into separated groups, they're not mixed together.
How would I fix this?
CodePudding user response:
out = (s.groupby(s.map(type), sort=False)
.apply(lambda x: pd.Series(x.sort_values(ascending=False).tolist(), index=x.index)))
out
0 98
1 hello
2 98.9
3 b
4 4
5 1
6 6.7
7 a
8 1.4
dtype: object
CodePudding user response:
I just figured out a solution myself, it's a bit long an inefficient. I would still prefer better solutions though.
This is how I did it:
print(
s.to_frame().groupby([[*map(type, s)]], sort=False)
.apply(lambda x: x.reindex(x.index[::-1])
.rename(index=dict(zip(x.index[::-1], x.index))))
.reset_index(level=0, drop=True)
.sort_index().squeeze().rename(index=None)
)
Output:
0 98
1 hello
2 98.9
3 b
4 4
5 1
6 6.7
7 a
8 1.4
dtype: object
I use to_frame
to convert this Series
into a DataFrame
, and I use map
to give me the types of all the values. After that, I use groupby
to group them and apply
and rename
to reverse the order/index of them. The next step is to use reset_index
to reset the index and sort the values by the index using sort_index
. Then, I just use squeeze
to convert this DataFrame
to a Series
again, and rename
to remove the index name.