根据列名保留ID和其他行的Python重塑

时间:2018-09-26 10:09:39

标签: python pandas

重塑df的最佳方法是什么,以便它根据列名的相似性来堆叠列,同时在新列中保留列名的唯一ID部分?

我有一个类似于以下的df(我的实际数据还包括需要保留的NaN值):

df = pandas.DataFrame({"RX_9mm": scipy.randn(5), "RY_9mm": scipy.randn(5),"TX_9mm": scipy.randn(5), "TY_9mm": scipy.randn(5), "RX_10mm": scipy.randn(5), "RY_10mm": scipy.randn(5),"TX_10mm": scipy.randn(5), "TY_10mm": scipy.randn(5), "time": range(5)})

    RX_9mm  RY_9mm  TX_9mm  TY_9mm  RX_10mm  RY_10mm  TX_10mm  TY_10mm  time
0 -0.1444  2.1319  1.9665  0.1773   0.5156  -1.8461   0.9122   1.1285     0
1  1.4831 -0.8773 -1.0112 -0.0010   1.4532  -1.3721   0.6894  -0.1781     1
2  0.3685  0.2148 -1.2216  0.0098  -1.1427  -0.1851   0.3890   0.9552     2
3  0.6843 -2.0279 -1.1342 -0.8869   0.2718  -2.4857  -1.0496  -0.4286     3
4 -1.5625 -0.2733 -0.1243 -1.2248  -0.7403  -0.5840   0.1797  -0.7014     4

但是我需要它看起来像这样:

       RX      RY      TX      TY time   ID
0 -0.1444  2.1319  1.9665  0.1773    0  9mm
1  1.4831 -0.8773 -1.0112 -0.0010    1  9mm
2  0.3685  0.2148 -1.2216  0.0098    2  9mm
3  0.6843 -2.0279 -1.1342 -0.8869    3  9mm
4 -1.5625 -0.2733 -0.1243 -1.2248    4  9mm
5  0.5156 -1.8461  0.9122  1.1285    0 10mm  
6  1.4532 -1.3721  0.6894 -0.1781    1 10mm
7 -1.1427 -0.1851  0.3890  0.9552    2 10mm
8  0.2718 -2.4857 -1.0496 -0.4286    3 10mm
9 -0.7403 -0.5840  0.1797 -0.7014    4 10mm

我尝试使用Chang She的“基于列标签重塑熊猫中的数据框”示例中的以下代码

但是,当我使用以下代码时:

id = df.ix[:, ['time']]
df.columns = pandas.MultiIndex.from_tuples([tuple(c.split('_')) for c in df.columns])
pandas.merge(df.stack(0).reset_index(1), id, left_index=True, right_index=True)

我得到:

       RX      RY      TX      TY      RX      RY      TX      TY time
      9mm     9mm     9mm     9mm    10mm    10mm    10mm    10mm  NaN
0 -0.1444  2.1319  1.9665  0.1773  0.5156 -1.8461  0.9122  1.1285    0
1  1.4831 -0.8773 -1.0112 -0.0010  1.4532 -1.3721  0.6894 -0.1781    1
2  0.3685  0.2148 -1.2216  0.0098 -1.1427 -0.1851  0.3890  0.9552    2
3  0.6843 -2.0279 -1.1342 -0.8869  0.2718 -2.4857 -1.0496 -0.4286    3
4 -1.5625 -0.2733 -0.1243 -1.2248 -0.7403 -0.5840  0.1797 -0.7014    4

我了解新列是具有测量值(RX,RY等)和ID(9mm,10mm)级别的多层,但是我不了解如何将测量值堆叠到同一列中,同时保持ID作为新列。

如果有人能解释我在做错什么来获得此输出而不是在堆积的列上,我将不胜感激。

谢谢

1 个答案:

答案 0 :(得分:3)

您可以简化您的解决方案,不需要最后一个merge,因为第一步中set_index将列time转换为index

df = df.set_index('time')
#expand=True in columns create MultiIndex
df.columns = df.columns.str.split('_', expand=True)
#rename_axis set MultiIndex names for names of columns after reset index
df = df.stack(dropna=False).rename_axis(['time','ID']).reset_index()
print (df)
   time    ID        RX        RY        TX        TY
0     0  10mm -0.549487 -0.349412 -0.620500  0.992223
1     0   9mm  0.831292 -2.465550 -0.863001 -1.335898
2     1  10mm  0.214057 -0.136649  1.831669 -0.672306
3     1   9mm -0.372416 -1.633798 -0.414518 -1.426492
4     2  10mm  0.480018  1.575599 -1.330841 -0.780036
5     2   9mm  0.352044 -1.008269  1.339841  0.423539
6     3  10mm -0.822354  0.002455 -1.099829  0.060929
7     3   9mm  1.336161 -0.066224 -1.111453  1.651180
8     4  10mm  0.627119 -0.419848  1.052179 -0.426928
9     4   9mm  0.701500 -0.833526  2.563398  0.749432

如果可以更改列的排序顺序,请使用numpy.r_

df = df[np.r_[df.columns[2:], df.columns[:2]]]
print (df)
         RX        RY        TX        TY  time    ID
0 -0.549487 -0.349412 -0.620500  0.992223     0  10mm
1  0.831292 -2.465550 -0.863001 -1.335898     0   9mm
2  0.214057 -0.136649  1.831669 -0.672306     1  10mm
3 -0.372416 -1.633798 -0.414518 -1.426492     1   9mm
4  0.480018  1.575599 -1.330841 -0.780036     2  10mm
5  0.352044 -1.008269  1.339841  0.423539     2   9mm
6 -0.822354  0.002455 -1.099829  0.060929     3  10mm
7  1.336161 -0.066224 -1.111453  1.651180     3   9mm
8  0.627119 -0.419848  1.052179 -0.426928     4  10mm
9  0.701500 -0.833526  2.563398  0.749432     4   9mm