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, 98and it's now98, 4, 1.The float order was
1.4, 6.7, 98.9and 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.
