简体   繁体   中英

Flatten multiple index into a single column

Assuming the following DataFrame:

     A    B    C    D    E    F
0   d1   10  d11   10  d21   10
1   d2   30  d12   30  d22   30
2   d3   40  d13   40  d23   40
3   d4  105  d14  105  d24  105
4   d5   10  d15   10  d25   10
5   d6   30  d16   30  d26   30
6   d7   40  d17   40  d27   40
7   d8   10  d18   10  d28   10
8   d9    5  d19    5  d29    5
9  d10   10  d20   10  d30   10

How do I merge all the descriptions into a single column that is associated with the respective value ?

   description  value
0           d1     10
1           d2     30
2           d3     40
3           d4    105
4           d5     10
5           d6     30
6           d7     40
7           d8     10
8           d9      5
9          d10     10
10         d11     10
11         d12     30
12         d13     40
13         d14    105
14         d15     10
15         d16     30
16         d17     40
17         d18     10
18         d19      5
19         d20     10
20         d21     10
21         d22     30
22         d23     40
23         d24    105
24         d25     10
25         d26     30
26         d27     40
27         d28     10
28         d29      5
29         d30     10

Take note that some descriptions of the original dataframe could have blank values and descriptions

I have tried

pd.melt( id_vars=['A','C','E'], value_vars=['B','D','F'])

but it doesn't get the result I want

You can select pair and unpair column first by iloc , create numpy array by values , transpose and flattening by ravel :

a = df.iloc[:, ::2].values.T.ravel()
b = df.iloc[:, 1::2].values.T.ravel()

Or if need select values by columns names:

a = df[['A','C','E']].values.T.ravel()
b = df[['B','D','F']].values.T.ravel()

And last use DataFrame constructor:

df = pd.DataFrame({'description': a, 'value':b})
print (df.head(10))
  description  value
0          d1     10
1          d2     30
2          d3     40
3          d4    105
4          d5     10
5          d6     30
6          d7     40
7          d8     10
8          d9      5
9         d10     10

Notice this work for your sample data.

pd.DataFrame({'v1':sum(df.select_dtypes(include=['object']).values.tolist(),[]),
              'v2':sum(df.select_dtypes(exclude=['object']).values.tolist(),[])})

Out[255]: 
     v1   v2
0    d1   10
1   d11   10
2   d21   10
3    d2   30
4   d12   30
5   d22   30
6    d3   40
7   d13   40
8   d23   40
9    d4  105

Try using concat

df_new = pd.DataFrame()
df_new['description']= pd.concat([df['A'], df['C'], df['E']], ignore_index=True)
df_new['value']= pd.concat([df['B'], df['D'], df['F']], ignore_index=True)

    description value
0   d1  10
1   d2  30
2   d3  40
3   d4  105
4   d5  10
5   d6  30
6   d7  40
7   d8  10
8   d9  5
9   d10 10
10  d11 10
11  d12 30
12  d13 40
13  d14 105
14  d15 10
15  d16 30
16  d17 40
17  d18 10
18  d19 5
19  d20 10
20  d21 10
21  d22 30
22  d23 40
23  d24 105
24  d25 10
25  d26 30
26  d27 40
27  d28 10
28  d29 5
29  d30 10

Just looking at the shape, you have 3 blocks to rearange:

pd.DataFrame(np.vstack(np.split(df.values,3,axis=1)),columns=['desc','value'])

gives the wanted output.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM