Reverse values in pd.Series by their value type
Question:
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 now 98, 4, 1
.
-
The float order was 1.4, 6.7, 98.9
and it’s now 98.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?
Answers:
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.
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
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?
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.
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