I am hoping someone can help me optimize the following Python/Pandas code. My code works, but I know there must be a cleaner and faster way to perform the operation under consideration.
I am looking for an optimized strategy because my use case will involve 16 unique ADC Types, as opposed to 4 in the example below. Also, my initial Pandas Series (i.e. ADC Type column), will be several 100,000 data points in length, rather than 8 in the example below.
import numpy as np
import pandas as pd
from enum import Enum
data_dict = {"RAW": [4000076160, 5354368, 4641792, 4289860736,
4136386944, 5440384, 4772864, 4289881216],
"ADC_TYPE": [3, 7, 8, 9,
3, 7, 8, 9]}
df = pd.DataFrame(data_dict)
print(df)
The initial DataFrame (i.e. df) is:
RAW ADC_TYPE
0 4000076160 3
1 5354368 7
2 4641792 8
3 4289860736 9
4 4136386944 3
5 5440384 7
6 4772864 8
7 4289881216 9
I then manipulate the DataFrame above using the following code:
unique_types = df["ADC_TYPE"].unique()
dict_concat = {"RAW": [],
"ADC_TYPE_3": [],
"ADC_TYPE_7": [],
"ADC_TYPE_8": [],
"ADC_TYPE_9": []}
df_concat = pd.DataFrame(dict_concat)
for adc_type in unique_types:
df_group = df.groupby(["ADC_TYPE"]).get_group(adc_type).rename(columns={"ADC_TYPE": f"ADC_TYPE_{adc_type}"})
df_concat = pd.concat([df_concat, df_group])
print(df_concat.sort_index())
The returned DataFrame (i.e. df_concat) is displayed below. The ordering of RAW and the associated ADC Type values must remain unchanged. I need the return DataFrame to look just like the DataFrame below.
RAW ADC_TYPE_3 ADC_TYPE_7 ADC_TYPE_8 ADC_TYPE_9
0 4.000076e 09 3.0 NaN NaN NaN
1 5.354368e 06 NaN 7.0 NaN NaN
2 4.641792e 06 NaN NaN 8.0 NaN
3 4.289861e 09 NaN NaN NaN 9.0
4 4.136387e 09 3.0 NaN NaN NaN
5 5.440384e 06 NaN 7.0 NaN NaN
6 4.772864e 06 NaN NaN 8.0 NaN
7 4.289881e 09 NaN NaN NaN 9.0
Thank you for your consideration.
CodePudding user response:
This is just a pivot table with a prefix.
Edit: To preserve sorting, you can reindex from the original dataframe
df = pd.DataFrame({'RAW': {0: 4000076160,
1: 5354368,
2: 4641792,
3: 4289860736,
4: 4136386944,
5: 5440384,
6: 4772864,
7: 4289881216},
'ADC_TYPE': {0: 3, 1: 7, 2: 8, 3: 9, 4: 3, 5: 7, 6: 8, 7: 9}})
out = df.pivot(index='RAW', columns = 'ADC_TYPE', values='ADC_TYPE').add_prefix('ACC_TYPE_').reset_index().rename_axis(None, axis=1)
out = out.set_index('RAW').reindex(df['RAW']).reset_index()
Output
RAW ACC_TYPE_3 ACC_TYPE_7 ACC_TYPE_8 ACC_TYPE_9
0 4000076160 3.0 NaN NaN NaN
1 5354368 NaN 7.0 NaN NaN
2 4641792 NaN NaN 8.0 NaN
3 4289860736 NaN NaN NaN 9.0
4 4136386944 3.0 NaN NaN NaN
5 5440384 NaN 7.0 NaN NaN
6 4772864 NaN NaN 8.0 NaN
7 4289881216 NaN NaN NaN 9.0
CodePudding user response:
Here is a way using str.get_dummies()
df2 = df.set_index('RAW')['ADC_TYPE'].astype(str).str.get_dummies()
(df2.mul(pd.to_numeric(df2.columns),axis=1)
.mask(lambda x: x.eq(0))
.rename('ADC_TYPE_{}'.format,axis=1)
.reset_index())
Here is a slightly different way using pd.get_dummies()
df2 = pd.get_dummies(df.set_index('RAW'),columns = ['ADC_TYPE'])
df2.mul((df2.columns.str.split('_').str[-1]).astype(int)).where(lambda x: x.ne(0))
You can also use set_index()
and unstack()
(df.set_index(['RAW',df['ADC_TYPE'].astype(str).map('ADC_TYPE_{}'.format)])['ADC_TYPE']
.unstack().reindex(df['RAW']).reset_index())
Output:
RAW ADC_TYPE_3 ADC_TYPE_7 ADC_TYPE_8 ADC_TYPE_9
0 4000076160 3.0 NaN NaN NaN
1 5354368 NaN 7.0 NaN NaN
2 4641792 NaN NaN 8.0 NaN
3 4289860736 NaN NaN NaN 9.0
4 4136386944 3.0 NaN NaN NaN
5 5440384 NaN 7.0 NaN NaN
6 4772864 NaN NaN 8.0 NaN
7 4289881216 NaN NaN NaN 9.0
CodePudding user response:
I liked the idea of using get_dummies
, so I modified it a bit:
df = (pd.get_dummies(df, 'ADC_TYPE', '_', columns=['ADC_TYPE'])
.replace(1, np.nan)
.apply(lambda x: x.fillna(df['ADC_TYPE']))
.replace(0, np.nan))
Output:
RAW ADC_TYPE_3 ADC_TYPE_7 ADC_TYPE_8 ADC_TYPE_9
0 4000076160 3.0 NaN NaN NaN
1 5354368 NaN 7.0 NaN NaN
2 4641792 NaN NaN 8.0 NaN
3 4289860736 NaN NaN NaN 9.0
4 4136386944 3.0 NaN NaN NaN
5 5440384 NaN 7.0 NaN NaN
6 4772864 NaN NaN 8.0 NaN
7 4289881216 NaN NaN NaN 9.0
CodePudding user response:
Using crosstab
:
out = pd.crosstab(
df["RAW"], df["ADC_TYPE"], values=df["ADC_TYPE"], aggfunc="first"
).rename_axis(None, axis=1)
out.columns = out.columns.map("ADC_TYPE_{}".format)
out = out.reindex(df["RAW"]).reset_index()
print(out):
RAW ADC_TYPE_3 ADC_TYPE_7 ADC_TYPE_8 ADC_TYPE_9
0 4000076160 3.0 NaN NaN NaN
1 5354368 NaN 7.0 NaN NaN
2 4641792 NaN NaN 8.0 NaN
3 4289860736 NaN NaN NaN 9.0
4 4136386944 3.0 NaN NaN NaN
5 5440384 NaN 7.0 NaN NaN
6 4772864 NaN NaN 8.0 NaN
7 4289881216 NaN NaN NaN 9.0