Alternative code:
Code below uses .stack()
, .unstack()
and .pivot_table()
. It selectively only picks column names that have the strings small
, large
,con
specified in list key
to be split.
Note:
- The output is aggregated by
aggfunc=np.max
in the .pivot_table()
. This could be changed to any other type of aggregation method as needed such as np.min
, np.sum
, or a custom function.
- The original column names were changed to lower case, except
Time
Code:
# Import libraries
import pandas as pd
# Create DataFrame (copy pasted from question above)
data = {'Time': ['12/1/19 0:00', '12/1/19 0:05'],
'Small_1': [1, 0],
'Large_1': [0, 0],
'Con_1': [0, 0],
'Small_2': [0, 0],
'Large_2': [0, 0],
'Con_2': [0, 0],
'Small_10': [1, 0],
'large_10': [0, 0],
'Con_10': [0, 0],
'Some_other_value': [78, 96],
}
df = pd.DataFrame(data)
# Set Time as index
df = df.set_index('Time')
# Rename columns
df.columns = df.columns.str.lower() # change case to lower
# Stack
df = df.stack().reset_index() # convert columns to rows
# Split based on condition
key = ['small', 'large','con'] # Column names to be split
df['col1'] = df['level_1'].apply(lambda x: x.split('_')[0] if x.split('_')[0] in key else x)
df['New_Column'] = df['level_1'].apply(lambda x: x.split('_')[1] if x.split('_')[0] in key else np.NaN)
# Drop/rename columns
df = df.drop(['level_1'], axis=1)
df.columns.name=''
# Pivot using aggregate function: np.max
df = df.pivot_table(index=['Time', 'New_Column'], columns='col1', values=0, aggfunc=np.max)
# Rearrange
df = df.reset_index()
df.columns.name=''
df = df[['Time','small', 'large', 'con', 'New_Column']]
Output
print(df)
Time small large con New_Column
0 12/1/19 0:00 1 0 0 1
1 12/1/19 0:00 1 0 0 10
2 12/1/19 0:00 0 0 0 2
3 12/1/19 0:05 0 0 0 1
4 12/1/19 0:05 0 0 0 10
5 12/1/19 0:05 0 0 0 2