带有占位列表的熊猫wide_to_long

时间:2019-11-29 15:25:29

标签: python pandas

我目前有以下数据框:

        1_1       1_2       1_3       1_4       1_5       2_1  ...       9_5      10_1      10_2      10_3      10_4      10_5

0  0.049400  0.063812  0.097736 -0.077222  0.112779 -0.201620  ...  0.138246  0.015369 -0.083559 -0.186949  0.158505 -0.046787 
1 -0.169837  0.093606  0.043157  0.095289 -0.078525 -0.026500  ... -0.054344  0.008955  0.045036  0.198438  0.197416 -0.057831 
2 -0.192915  0.001477  0.077699  …

我想获得这样的东西:

cat     u       i       mouse       

0       1       1      0.049400 
1       1       1     -0.169837
2       1       1     -0.192915
0       1       2      0.063812
1       1       2      0.093606
2       1       2      0.001477
…

从本质上讲,这些行表示cat列的值,下划线之前的数字表示u列,之后的数字表示i列。最后,鼠标列是先前因素组合的值。

但是,该解决方案应该适用于这种格式的任何数据。

到目前为止,考虑到我可以访问u(在本例中为1,2,3,4,5,6,7,8,9,10)和i(1,2,3, 3,4,5),但是该解决方案也应适用于不同的列表和不同的行数。

u_seq_stub = [u + '_' for u in u_seq] 
df = pd.wide_to_long(df, u_seq_stub, i='u', j='i').reset_index().rename(columns={'_':'u'})

但是这不起作用,并抛出“ KeyError:” [Index(['userid'],dtype ='object')]都不在[columns]中”“ ...我也咨询过this,似乎与我想要的并没有什么不同,但一定有我误会的地方。

在此先感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

将所有列的split用于MultiIndex,然后按DataFrame.unstack进行整形,按DataFrame.rename_axis更改新列名称的级别,最后按{{3}将其转换为列}}:

df.columns = df.columns.str.split('_', expand=True)
df = df.unstack().rename_axis(('u','i','cat')).reset_index(name='mouse')
print (df.head(10))
   u  i  cat     mouse
0  1  1    0  0.049400
1  1  1    1 -0.169837
2  1  1    2 -0.192915
3  1  2    0  0.063812
4  1  2    1  0.093606
5  1  2    2  0.001477
6  1  3    0  0.097736
7  1  3    1  0.043157
8  1  3    2  0.077699
9  1  4    0 -0.077222

您的解决方案应首先在Series.reset_index中使用参数sep进行更改,然后再通过wide_to_long进行一些数据清理来重新设计:

u_seq_stub = ['1','2',...,'9','10']
#alternative
#u_seq_stub = [str(x) for x in range(1,11)]


df = (pd.wide_to_long(df.reset_index(), 
                     u_seq_stub, 
                     i='index', 
                     j='i', 
                     sep='_')
      .stack()
      .reset_index(name='mouse')
      .rename(columns={'index':'cat', 'level_2':'u'})
      .astype({'i':int, 'u':int})
      .sort_values(['u','i','cat'])
      )
print (df.head(10))
    cat  i  u     mouse
0     0  1  1  0.049400
12    1  1  1 -0.169837
24    2  1  1 -0.192915
3     0  2  1  0.063812
15    1  2  1  0.093606
25    2  2  1  0.001477
5     0  3  1  0.097736
17    1  3  1  0.043157
26    2  3  1  0.077699
7     0  4  1 -0.077222

答案 1 :(得分:1)

DataFrame.melt + Series.str.splitexpand=True一起使用。要创建cat列,您可以使用GroupBy.cumcount

new_df=df.melt(var_name='u_i',value_name='mouse')
new_df['cat']=new_df.groupby('u_i').cumcount()
new_df[['u','i']]=new_df['u_i'].str.split('_',expand=True)
new_df=new_df.drop('u_i',axis=1).reindex(columns=['cat','u','i','mouse'])

print(new_df)

   cat  u  i     mouse
0    0  1  1  0.049400
1    1  1  1 -0.169837
2    2  1  1 -0.192915
3    0  1  2  0.063812
4    1  1  2  0.093606
5    2  1  2  0.001477
6    0  1  3  0.097736
7    1  1  3  0.043157
8    2  1  3  0.077699