重构没有真正索引的pandas数据帧

时间:2017-08-26 19:39:02

标签: python pandas dataframe statsmodels

过去几周我一直试图构建一个回归输出的数据框,而且我已经完成了大部分工作。我现在正试图围绕列中的某些关键字对其进行重新整理,据我所知,该列不可调用。

我的数据框的简化版本如下:

?           coef pval  se   rsq
Intercept   1    0     .1   .1
Cash        2    0.2   .05  .1
Food        2    0.05  .2   .1
Intercept   3    0     .1   .2
Cash        1    0.01  .2   .2
Food        2    0.3   .1   .2
Zone        1    0.4   .3   .2

我想要实现的目标是:

                (1)      (2)
Intercept coef   1        3
Intercept pval   0        0
Intercept se     0.1      0.1
Cash coef        2        1
Cash pval        0.2      0.01
Cash se          0.05     0.2
Food coef        2        2
Food pval        0.05     0.3
Food se          0.2      0.1
Zone coef        NaN      1
Zone pval        NaN      0.4
Zone se          NaN      0.3
rsq              0.1      0.2

到目前为止,我已经尝试了几种方法,有希望的是使用r-squared(rsq)作为索引进行重新整形 - > RegTable = RegTable.pivot(index='rsq', columns=['pval', 'coef', 'robust_se'])

然而,这会返回错误ValueError: all arrays must be same length。一些研究让我觉得这是因为截至目前,zone = NaN由回归表示,根本没有区域行,但我不确定如何解决它。另外,我一直无法弄清楚如何调用我标识为#34;?"的列。使用PANDAS - 它没有在CSV输出中标记。此外,这种方法似乎有问题,因为两次回归具有相同的r平方的概率,它将最终抛出新的错误或平均每个值,这两者都不是完全合乎需要的。

3 个答案:

答案 0 :(得分:3)

让我们试试这个:

df.set_index(['rsq','?']).stack().unstack([0]).T\
  .reset_index().T.rename_axis([None,None])\
  .rename(columns={0:'(1)',1:'(2)'})\
  .sort_index()

df:

           ?  coef  pval    se  rsq
0  Intercept     1  0.00  0.10  0.1
1       Cash     2  0.20  0.05  0.1
2       Food     2  0.05  0.20  0.1
3  Intercept     3  0.00  0.10  0.2
4       Cash     1  0.01  0.20  0.2
5       Food     2  0.30  0.10  0.2
6       Zone     1  0.40  0.30  0.2

输出:

                 (1)   (2)
Cash      coef  2.00  1.00
          pval  0.20  0.01
          se    0.05  0.20
Food      coef  2.00  2.00
          pval  0.05  0.30
          se    0.20  0.10
Intercept coef  1.00  3.00
          pval  0.00  0.00
          se    0.10  0.10
Zone      coef   NaN  1.00
          pval   NaN  0.40
          se     NaN  0.30
rsq             0.10  0.20

答案 1 :(得分:2)

这种解决方案背后的直觉是将数据帧分成两个大致相等的部分。这里的假设是你只有两组数据点,所以这变得易于管理。

print(df)

           coef  pval    se  rsq
Intercept     1  0.00  0.10  0.1
Cash          2  0.20  0.05  0.1
Food          2  0.05  0.20  0.1
Intercept     3  0.00  0.10  0.2
Cash          1  0.01  0.20  0.2
Food          2  0.30  0.10  0.2
Zone          1  0.40  0.30  0.2


df_ = df.reset_index().iloc[:, :-1]

df2 = df_.iloc[df_['index'].drop_duplicates(keep='first').to_frame().index]
df1 = df_.iloc[df_['index'].drop_duplicates(keep='last')\
                 .to_frame().index.difference(df2.index)]

完成后,每件必须堆叠,然后沿第一轴连接。

out = pd.concat([df1.set_index('index').stack(),\
                 df2.set_index('index').stack()], 1)
out.append(pd.DataFrame([df.rsq.unique()], index=[('rsq', '')]))
out.columns = ['1', '2']

print(out) 

                   1     2
index                     
Cash      coef  1.00  2.00
          pval  0.01  0.20
          se    0.20  0.05
Food      coef  2.00  2.00
          pval  0.30  0.05
          se    0.10  0.20
Intercept coef  3.00  1.00
          pval  0.00  0.00
          se    0.10  0.10
Zone      coef   NaN  1.00
          pval   NaN  0.40
          se     NaN  0.30
rsq             0.10  0.20

答案 2 :(得分:1)

这里有一个稍微偏心的方法,可以不分成两个数据帧。

此解决方案重命名索引以跟踪它们所属的回归,并在NaN时添加缺少的字段(如Zone的情况)。
然后groupbystack,并将列表列拆分为(1)(2)列(尽管它已被广义化以处理与数据中出现的一样多的回归)。

df为:

            coef pval  se   rsq
Intercept   1    0     .1   .1
Cash        2    0.2   .05  .1
Food        2    0.05  .2   .1
Intercept   3    0     .1   .2
Cash        1    0.01  .2   .2
Food        2    0.3   .1   .2
Zone        1    0.4   .3   .2

将索引值重命名为Intercept0Intercept1等:

measures = df.index.unique()
found = {m:0 for m in measures}

for i, name in enumerate(df.index):
    if np.max(list(found.values())) > found[name]+1:
        df.loc["{}{}".format(name, found[name])] = np.nan
        found[name] += 1
    df.index.values[i] = "{}{}".format(name, found[name])
    found[name] += 1

df
            coef  pval    se  rsq
Intercept0   1.0  0.00  0.10  0.1
Cash0        2.0  0.20  0.05  0.1
Food0        2.0  0.05  0.20  0.1
Intercept1   3.0  0.00  0.10  0.2
Cash1        1.0  0.01  0.20  0.2
Food1        2.0  0.30  0.10  0.2
Zone1        1.0  0.40  0.30  0.2
Zone0        NaN   NaN   NaN  NaN

现在排列行,以便将每个回归中的元素组合在一起。 (这主要是为了在正确的位置获取NaN行。)

order_by_reg = sorted(df.index, key=lambda x: ''.join(reversed(x)))
df = df.loc[order_by_reg]

df
            coef  pval    se  rsq
Food0        2.0  0.05  0.20  0.1
Zone0        NaN   NaN   NaN  NaN
Cash0        2.0  0.20  0.05  0.1
Intercept0   1.0  0.00  0.10  0.1
Food1        2.0  0.30  0.10  0.2
Zone1        1.0  0.40  0.30  0.2
Cash1        1.0  0.01  0.20  0.2
Intercept1   3.0  0.00  0.10  0.2

最后,groupbystack,并将结果列的列分割为apply(pd.Series)

gb = (df.groupby(lambda x: x[:-1])
        .agg(lambda x: list(x))
        .stack()
        .apply(lambda pair: pd.Series({"({})".format(i):el for i, el in enumerate(pair)})))

gb
                 (0)   (1)
Cash      coef  2.00  1.00
          pval  0.20  0.01
          se    0.05  0.20
          rsq   0.10  0.20
Food      coef  2.00  2.00
          pval  0.05  0.30
          se    0.20  0.10
          rsq   0.10  0.20
Intercept coef  1.00  3.00
          pval  0.00  0.00
          se    0.10  0.10
          rsq   0.10  0.20
Zone      coef   NaN  1.00
          pval   NaN  0.40
          se     NaN  0.30
          rsq    NaN  0.20