2017-03-02 160 views
3

我有一个数据集(171列),我考虑到我的数据帧时,它看起来像这样way-大熊猫列值的行值

ANO MNO UJ2010 DJ2010 UF2010 DF2010 UM2010 DM2010 UA2010 DA2010 ... 
1 A 113 06/01/2010 129 06/02/2010 143 06/03/2010 209 05/04/2010 ... 
2 B 218 06/01/2010 211 06/02/2010 244 06/03/2010 348 05/04/2010 ... 
3 C 22 06/01/2010 114 06/02/2010 100 06/03/2010 151 05/04/2010 ... 

现在我想改变我的数据帧像这样 -

ANO MNO Time  Unit 
    1 A 06/01/2010 113 
    1 A 06/02/2010 129 
    1 A 06/03/2010 143 
    2 B 06/01/2010 218 
    2 B 06/02/2010 211 
    2 B 06/03/2010 244 
    3 C 06/01/2010 22 
    3 C 06/02/2010 114 
    3 C 06/03/2010 100 
.... 
..... 

我试图用pd.melt,但我认为这并不fullfill我的目的。

这将是巨大的,如果有人帮助我在这个特殊的问题:)

回答

1

您可以通过stack重塑,但先在列MultiIndex%//。通过2

MultiIndexTimeUnit映射对由地板除法(//)第二级的MultiIndex,每对差异是由模除法(%)创建。

然后stack使用//创建的最后一级,并在index中创建新级别的MultiIndex,这不是必需的,因此被reset_index(level=2, drop=True)删除。

最后一次reset_index用于将第一级和第二级转换为columns

[[1,0]]用于更改排序的交换列。

df = df.set_index(['ANO','MNO']) 
cols = np.arange(len(df.columns)) 
df.columns = [cols % 2, cols // 2] 

print (df) 
      0   1 0   1 0   1 0   1 
      0   0 1   1 2   2 3   3 
ANO MNO                  
1 A 113 06/01/2010 129 06/02/2010 143 06/03/2010 209 05/04/2010 
2 B 218 06/01/2010 211 06/02/2010 244 06/03/2010 348 05/04/2010 
3 C  22 06/01/2010 114 06/02/2010 100 06/03/2010 151 05/04/2010 

df = df.stack()[[1,0]].reset_index(level=2, drop=True).reset_index() 
df.columns = ['ANO','MNO','Time','Unit'] 
print (df) 
    ANO MNO  Time Unit 
0  1 A 06/01/2010 113 
1  1 A 06/02/2010 129 
2  1 A 06/03/2010 143 
3  1 A 05/04/2010 209 
4  2 B 06/01/2010 218 
5  2 B 06/02/2010 211 
6  2 B 06/03/2010 244 
7  2 B 05/04/2010 348 
8  3 C 06/01/2010 22 
9  3 C 06/02/2010 114 
10 3 C 06/03/2010 100 
11 3 C 05/04/2010 151 

编辑:

#last column is missing 
print (df) 
    ANO MNO UJ2010  DJ2010 UF2010  DF2010 UM2010  DM2010 UA2010 
0 1 A  113 06/01/2010  129 06/02/2010  143 06/03/2010  209 
1 2 B  218 06/01/2010  211 06/02/2010  244 06/03/2010  348 
2 3 C  22 06/01/2010  114 06/02/2010  100 06/03/2010  151 

df = df.set_index(['ANO','MNO']) 
#MultiIndex is created by first character of column names with all another 
df.columns = [df.columns.str[0], df.columns.str[1:]] 
print (df) 
      U   D  U   D  U   D  U 
     J2010  J2010 F2010  F2010 M2010  M2010 A2010 
ANO MNO                
1 A  113 06/01/2010 129 06/02/2010 143 06/03/2010 209 
2 B  218 06/01/2010 211 06/02/2010 244 06/03/2010 348 
3 C  22 06/01/2010 114 06/02/2010 100 06/03/2010 151 


#stack add missing values, replace them by NaN 
df = df.stack().reset_index(level=2, drop=True).reset_index() 
df.columns = ['ANO','MNO','Time','Unit'] 
print (df) 
    ANO MNO  Time Unit 
0  1 A   NaN 209 
1  1 A 06/02/2010 129 
2  1 A 06/01/2010 113 
3  1 A 06/03/2010 143 
4  2 B   NaN 348 
5  2 B 06/02/2010 211 
6  2 B 06/01/2010 218 
7  2 B 06/03/2010 244 
8  3 C   NaN 151 
9  3 C 06/02/2010 114 
10 3 C 06/01/2010 22 
11 3 C 06/03/2010 100 
+0

能否请你解释一下代码片段:) –

+0

肯定,给我秒 – jezrael

+0

按列行开关,你的代码工作,但现在的问题是,我缺少值到一个特定的列。实际上,这种做法是左移其价值观到其他专栏。我能够理解你的情况吗? –

3

使用pd.lreshape作为过滤列之后的紧密替代pd.melt到不同标题下被分组。

通过使用pd.lreshape,当你注入一个字典对象,因为它是groups参数,按键将采取新的头名并且作为值这个dict列名的全部名单将是单头下施放。因此,它会在转换后生成一个长格式的DF

最后对DF w.r.t进行排序,将未使用的列对齐。

然后,reset_index(drop=True)结束时通过放弃中间索引将索引轴重新标注为默认整数值。

d = pd.lreshape(df, {"Time": df.filter(regex=r'^D').columns, 
        "Unit": df.filter(regex=r'^U').columns}) 

d.sort_values(['ANO', 'MNO']).reset_index(drop=True) 

enter image description here


如果有在分组列的长度不匹配,则:

from itertools import groupby, chain 

unused_cols = ['ANO', 'MNO'] 
cols = df.columns.difference(unused_cols) 

# filter based on the common strings starting from the first slice upto end. 
fnc = lambda x: x[1:] 
pref1, pref2 = "D", "U" 

# Obtain groups based on a common interval of slices. 
groups = [list(g) for n, g in groupby(sorted(cols, key=fnc), key=fnc)] 

# Fill single length list with it's other char counterpart. 
fill_missing = [i if len(i)==2 else i + 
       [pref1 + i[0][1:] if i[0][0] == pref2 else pref2 + i[0][1:]] 
       for i in groups] 

# Reindex based on newly obtained column names. 
df = df.reindex(columns=unused_cols + list(chain(*fill_missing))) 

继续与pd.lreshape相同的步骤如上所述,但这次dropna=False包括参数。

+2

pd.lreshape是伟大的+1 :-) – pansen

+0

我可能是错的,但无法找到任何关于'pd的文档。 lreshape',你能解释一下代码吗?你能给我参考文档吗? –

+0

*我更新了我的帖子。*如果您使用Jupyter,'pd.lreshape ??'应该在弹出窗口中向您显示底层代码。 AFAIK,目前它仍处于实验阶段,因此它缺少文档页面。 –

0

对此,您可以使用ilocpd.concat。解决方法很简单 - 只是栈中所有相关列(其中通过ILOC选择)垂直一个又一个将它们连接起来:

def rename(sub_df): 
    sub_df.columns = ["ANO", "MNO", "Time", "Unit"] 
    return sub_df 

pd.concat([rename(df.iloc[:, [0, 1, x+1, x]]) 
      for x in range(2, df.shape[1], 2)]) 

    ANO  MNO  Time Unit 
0 1  A 06/01/2010 113 
1 2  B 06/01/2010 218 
2 3  C 06/01/2010 22 
0 1  A 06/02/2010 129 
1 2  B 06/02/2010 211 
2 3  C 06/02/2010 114 
0 1  A 06/03/2010 143 
1 2  B 06/03/2010 244 
2 3  C 06/03/2010 100 
0 1  A 05/04/2010 209 
1 2  B 05/04/2010 348 
2 3  C 05/04/2010 151 
+0

因为我说我有171列,所以我需要改变'concat'方法中的参数吗? –

+0

@pdfarhad不,你已经通过'df.shape [1]'进入了。范围自动调整到您的输入数据帧。 – pansen