干净的切片方式 + 堆叠 pandas 数据框

Clean way of slicing + stacking pandas dataframe

我有一个 Pandas DataFrame,比如说 df,它有 1099 行 x 33 行。我需要用另一个软件处理原始文件,但它的格式不正确。这就是为什么我试图获得 pandas.

的良好格式

问题很简单:df是由一列标识符构成的(实际是7列,下面的例子只有3列),然后按月对应的结果。明确地说,就像

A    B    C    date1result  date2result  date2result
a1   b1   c1       12           15           17
a2   b2   c3        5            8            3

但要进行处理,我需要每个结果一行,并为日期添加一列。在给定的示例中,它将是

A    B    C      result       date  
a1   b1   c1       12         date1 
a1   b1   c1       15         date2
a1   b1   c1       17         date3
a2   b2   c3        5         date1
a2   b2   c3        8         date2
a2   b2   c3        3         date3

所以更准确地说,我手动编辑了所有带有日期的列名(在 read_excel 之后,看起来像 '01/01/2015 0:00:00' 或类似的东西,并且我无法访问它们...作为次要问题,有人知道如何访问从 .xlsx 中的日期字段导入的列吗?),因此日期列名称现在为 2015_01、2015_02... 2015_12, 2016_01, ..., 2016_12, 第 5 个是 'Account','Customer Name','Postcode','segment' 和 'Rep'。所以我尝试了以下代码:

core = df.loc[:,('Account','Customer Name','Postcode','segment','Rep')]

df_final=pd.Series([])
for year in [2015,2016]:
    for month in range(1, 13):
        label = "%i_%02i" % (year,month)
        date = []
        for i in range(core.shape[0]):
            date.append("01/%02i/%i"%(month,year))  
        df_date=pd.Series(date) #I don't know to create this 1xn df
        df_final = df_final.append(pd.concat([core, df[label], df_date], axis=1))

大致可行,但非常不干净:我得到一个 (26376, 30) 形状的 df_final,第一列是日期,然后是结果,当然还有 '2015_01 ' 作为列名,然后所有的 '2015_02' 到 '2016_12' 由 NaN 填充,最后是我的帐户', 'Customer Name', 'Postcode', 'segment' 和 'Rep' 列。有谁知道我如何以干净的方式完成这样的 "slicing+stacking"?

非常感谢。

编辑:大致是这个问题的反面:Stacking and shaping slices of DataFrame (pandas) without looping

我想你需要 melt:

df = pd.melt(df, id_vars=['A','B','C'], value_name='result', var_name='date')
print (df)
    A   B   C         date  result
0  a1  b1  c1  date1result      12
1  a2  b2  c3  date1result       5
2  a1  b1  c1  date2result      15
3  a2  b2  c3  date2result       8
4  a1  b1  c1  date3result      17
5  a2  b2  c3  date3result       3

然后转换to_datetime:

print (df)
    A   B   C  2015_01  2016_10  2016_12
0  a1  b1  c1       12       15       17
1  a2  b2  c3        5        8        3

df = pd.melt(df, id_vars=['A','B','C'], value_name='result', var_name='date')
df.date = pd.to_datetime(df.date, format='%Y_%m')
print (df)
    A   B   C       date  result
0  a1  b1  c1 2015-01-01      12
1  a2  b2  c3 2015-01-01       5
2  a1  b1  c1 2016-10-01      15
3  a2  b2  c3 2016-10-01       8
4  a1  b1  c1 2016-12-01      17
5  a2  b2  c3 2016-12-01       3