Home > Back-end >  Transpose Column data into rows from a dataframe
Transpose Column data into rows from a dataframe

Time:11-11

This is the Input

| Type - I | Type - II | Type - I | Type - II |
|----------|-----------|----------|-----------|
| 560      | 189       | 128      | 244       |
| 379      | 460       | 357      | 679       |
| 238      | 568       | 125      | 147       |
| 389      | 357       | 780      | 459       |

This is the Output desired

| Type - I | Type - II |   |   |
|----------|-----------|---|---|
| 560      | 189       |   |   |
| 128      | 244       |   |   |
| 379      | 460       |   |   |
| 357      | 679       |   |   |
| 238      | 568       |   |   |
| 125      | 147       |   |   |
| 389      | 357       |   |   |
| 780      | 459       |   |   |

Tried many ways but was not able to do it.

CodePudding user response:

You can de-duplicate the columns and stack:

(df.set_axis(pd.MultiIndex.from_frame(df.groupby(axis=1, level=0)
                                        .cumcount().reset_index()),
             axis=1)
   .stack()
   #.reset_index(drop=True) # uncomment if a clean index is needed
)

Output:

index  Type - I  Type - II
  0                       
0 0         560        189
  1         128        244
1 0         379        460
  1         357        679
2 0         238        568
  1         125        147
3 0         389        357
  1         780        459

CodePudding user response:

As I understand, you want to split your 3rd and 4th columns between 1rd and 2nd columns' rows.

In a hard-coded way:

1- You may declare a new pandas frame which has a 2 column and (2 * your previous_row).

2- Then assign Type-I and Type-II to even rows.

3- And, Left Type-I and Type-II to odd rows.

CodePudding user response:

Here is a way:

(df.stack()
.to_frame()
.assign(cc = lambda x: x.groupby(level=1).cumcount())
.set_index('cc',append=True)
.droplevel(0)[0]
.unstack(level=0))

CodePudding user response:

Another possible solution, based on the the idea of creating two sequences of indexes (even and odd), then concatenating the two dataframe blocks, and finally creating a new index with the sequence evens odds and sorting by index:

evens = [x for x in range(2*len(df)) if x % 2 == 0]
odds = [x for x in range(2*len(df)) if x % 2 != 0]

out = pd.concat([df.iloc[:,:2], df.iloc[:,2:]])
out.index = evens   odds
out = out.sort_index() 

Output:

  Type - I  Type - II
0       560        189
1       128        244
2       379        460
3       357        679
4       238        568
5       125        147
6       389        357
7       780        459

CodePudding user response:

If the columns are duplicates, you can take use that pattern in your reshaping by moving into numpy:

cols = df.columns.unique()
new_df = df.to_numpy().reshape(-1, len(cols))
pd.DataFrame(new_df, columns = cols)
   Type - I  Type - II
0       560        189
1       128        244
2       379        460
3       357        679
4       238        568
5       125        147
6       389        357
7       780        459

Another option is with pivot_longer from pyjanitor, where for this particular use case, you pass a regular expression with groups (to names_pattern) to aggregate the desired column labels into new groups (in names_to) - in this case we wish to keep the column label, so we use .value as a placeholder to initiate that:

# pip install pyjanitor
import pandas as pd
import janitor

df.pivot_longer(index = None, 
                names_to = '.value', 
                names_pattern = r"(. )", 
                sort_by_appearance=True) 
   Type - I  Type - II
0       560        189
1       128        244
2       379        460
3       357        679
4       238        568
5       125        147
6       389        357
7       780        459

  • Related