I'm trying to transform a pandas df that looks like:
import numpy as np
import pandas as pd
test_data = {'run': ['X', 'Y', 'A', 'B', 'C', 'D'],
'time': [np.nan, np.nan, 10, 20, 40, 60],
'temp': [np.nan, np.nan, 100, 120, 140, 160],
'press': [np.nan, np.nan, 200, 220, 240, 260],
'twist': [np.nan, np.nan, 300 ,320, 340, 360],
'output_site_1': [0, 0, 11, 12, 13, 14],
'output_site_2': [0, 1, 15, 16, 17, 18],
'output_site_3': [1, 0, 19, 20, 21, 22],
'output_site_4': [1, 1, 23, 24, 25, 26]
}
pd.DataFrame(test_data)
| run | time | temp | press | twist | output_site_1 | output_site_2 | output_site_3 | output_site_4 |
|---|---|---|---|---|---|---|---|---|
| X | NaN | NaN | NaN | NaN | 0 | 0 | 1 | 1 |
| Y | NaN | NaN | NaN | NaN | 0 | 1 | 0 | 1 |
| A | 10.0 | 100.0 | 200.0 | 300.0 | 11 | 15 | 19 | 23 |
| B | 20.0 | 120.0 | 220.0 | 320.0 | 12 | 16 | 20 | 24 |
| C | 40.0 | 140.0 | 240.0 | 340.0 | 13 | 17 | 21 | 25 |
| D | 60.0 | 160.0 | 260.0 | 360.0 | 14 | 18 | 22 | 26 |
into a df that looks like the one below:
transform_test_data = {'run': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D', 'D'],
'X': [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1],
'Y': [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
'time': [10, 10, 10, 10, 20, 20, 20, 20, 40, 40, 40, 40, 60, 60, 60, 60],
'temp': [100, 100, 100, 100, 120, 120, 120, 120, 140, 140, 140, 140, 160, 160, 160, 160],
'press': [200, 200, 200, 200, 220, 220, 220, 220, 240, 240, 240, 240, 260, 260, 260, 260],
'twist': [300 ,300, 300, 300, 320, 320, 320, 320, 340, 340, 340, 340, 360, 360, 360, 360],
'output': [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
}
pd.DataFrame(transform_test_data)
| run | X | Y | time | temp | press | twist | output |
|---|---|---|---|---|---|---|---|
| A | 0 | 0 | 10 | 100 | 200 | 300 | 11 |
| A | 0 | 1 | 10 | 100 | 200 | 300 | 12 |
| A | 1 | 0 | 10 | 100 | 200 | 300 | 13 |
| A | 1 | 1 | 10 | 100 | 200 | 300 | 14 |
| B | 0 | 0 | 20 | 120 | 220 | 320 | 15 |
| B | 0 | 1 | 20 | 120 | 220 | 320 | 16 |
| B | 1 | 0 | 20 | 120 | 220 | 320 | 17 |
| B | 1 | 1 | 20 | 120 | 220 | 320 | 18 |
| C | 0 | 0 | 40 | 140 | 240 | 340 | 19 |
| C | 0 | 1 | 40 | 140 | 240 | 340 | 20 |
| C | 1 | 0 | 40 | 140 | 240 | 340 | 21 |
| C | 1 | 1 | 40 | 140 | 240 | 340 | 22 |
| D | 0 | 0 | 60 | 160 | 260 | 360 | 23 |
| D | 0 | 1 | 60 | 160 | 260 | 360 | 24 |
| D | 1 | 0 | 60 | 160 | 260 | 360 | 25 |
| D | 1 | 1 | 60 | 160 | 260 | 360 | 26 |
I would like to take the rows 'X' and 'Y' and turn them into two seperate columns in the df and then remove them from the df. Doing so would add two new columns ('X' and 'Y') while also increasing the number for each run by run*(number-output-sites).
I need the method to be generalized such that it takes in a dataframe (like the first one) and returns a df (like the last one), can handle arbitrary number of inputs, and sites. There will always be a delineation between inputs and outputs as the first output will always be labeled 'output_site_1'.
I supplied 'test_data' and 'transformed_test_data' as dictionaries so if anyone felt kind enough to help out a stuck human (that's me!) it would be easy to create the two dataframes.