具有多个值变量的 Pandas 融化

Posted

技术标签:

【中文标题】具有多个值变量的 Pandas 融化【英文标题】:Pandas Melt with Multiple Value Vars 【发布时间】:2017-12-17 10:11:00 【问题描述】:

我有一个像这样的宽格式数据集

   Index Country     Variable 2000 2001 2002 2003 2004 2005
   0     Argentina   var1     12   15   18    17  23   29
   1     Argentina   var2     1    3    2     5   7    5
   2     Brazil      var1     20   23   25   29   31   32
   3     Brazil      var2     0    1    2    2    3    3

我想将我的数据重新整形为 long 以便年份、var1 和 var2 成为新列

  Index Country     year   var1 var2
  0     Argentina   2000   12   1
  1     Argentina   2001   15   3
  2     Argentina   2002   18   2
  ....
  6     Brazil      2000   20   0
  7     Brazil      2001   23   1

当我只有一个变量时,我可以通过编写代码来工作

df=(pd.melt(df,id_vars='Country',value_name='Var1', var_name='year'))

我不知道如何为 var1、var2、var3 等执行此操作。

【问题讨论】:

【参考方案1】:

numpy

years = df.drop(['Country', 'Variable'], 1)
y = years.values
m = y.shape[1]
c = df.Country.values
v = df.Variable.values

f0, u0 = pd.factorize(df.Country.values)
f1, u1 = pd.factorize(df.Variable.values)

w = np.empty((u1.size, u0.size, m), dtype=y.dtype)
w[f1, f0] = y

results = pd.DataFrame(dict(
        Country=u0.repeat(m),
        Year=np.tile(years.columns.values, u0.size),
    )).join(pd.DataFrame(w.reshape(-1, m * u1.size).T, columns=u1))

results

      Country  Year  var1  var2
0   Argentina  2000    12     1
1   Argentina  2001    15     3
2   Argentina  2002    18     2
3   Argentina  2003    17     5
4   Argentina  2004    23     7
5   Argentina  2005    29     5
6      Brazil  2000    20     0
7      Brazil  2001    23     1
8      Brazil  2002    25     2
9      Brazil  2003    29     2
10     Brazil  2004    31     3
11     Brazil  2005    32     3

【讨论】:

【参考方案2】:

选项 1

使用 melt 然后 unstack 用于 var1、var2 等...

(df1.melt(id_vars=['Country','Variable'],var_name='Year')
    .set_index(['Country','Year','Variable'])
    .squeeze()
    .unstack()
    .reset_index())

输出:

Variable    Country  Year  var1  var2
0         Argentina  2000    12     1
1         Argentina  2001    15     3
2         Argentina  2002    18     2
3         Argentina  2003    17     5
4         Argentina  2004    23     7
5         Argentina  2005    29     5
6            Brazil  2000    20     0
7            Brazil  2001    23     1
8            Brazil  2002    25     2
9            Brazil  2003    29     2
10           Brazil  2004    31     3
11           Brazil  2005    32     3

选项 2

使用pivot 然后stack

(df1.pivot(index='Country',columns='Variable')
   .stack(0)
   .rename_axis(['Country','Year'])
   .reset_index())

输出:

Variable    Country  Year  var1  var2
0         Argentina  2000    12     1
1         Argentina  2001    15     3
2         Argentina  2002    18     2
3         Argentina  2003    17     5
4         Argentina  2004    23     7
5         Argentina  2005    29     5
6            Brazil  2000    20     0
7            Brazil  2001    23     1
8            Brazil  2002    25     2
9            Brazil  2003    29     2
10           Brazil  2004    31     3
11           Brazil  2005    32     3

选项 3(ayhan 的解决方案)

使用set_indexstackunstack

(df.set_index(['Country', 'Variable'])
   .rename_axis(['Year'], axis=1)
   .stack()
   .unstack('Variable')
   .reset_index())

输出:

Variable    Country  Year  var1  var2
0         Argentina  2000    12     1
1         Argentina  2001    15     3
2         Argentina  2002    18     2
3         Argentina  2003    17     5
4         Argentina  2004    23     7
5         Argentina  2005    29     5
6            Brazil  2000    20     0
7            Brazil  2001    23     1
8            Brazil  2002    25     2
9            Brazil  2003    29     2
10           Brazil  2004    31     3
11           Brazil  2005    32     3

【讨论】:

我喜欢你以非常易于阅读的方式布置选项的方式:-) @piRSquared 谢谢。【参考方案3】:

你可以使用stack和unstack的组合来代替melt:

(df.set_index(['Country', 'Variable'])
   .rename_axis(['Year'], axis=1)
   .stack()
   .unstack('Variable')
   .reset_index())

Variable    Country  Year  var1  var2
0         Argentina  2000    12     1
1         Argentina  2001    15     3
2         Argentina  2002    18     2
3         Argentina  2003    17     5
4         Argentina  2004    23     7
5         Argentina  2005    29     5
6            Brazil  2000    20     0
7            Brazil  2001    23     1
8            Brazil  2002    25     2
9            Brazil  2003    29     2
10           Brazil  2004    31     3
11           Brazil  2005    32     3

【讨论】:

以上是关于具有多个值变量的 Pandas 融化的主要内容,如果未能解决你的问题,请参考以下文章

将具有多个 nan 值的 pandas 系列减少到一个集合会给出多个 nan 值

python pandas将数据框转换为具有多个值的字典

使用 Pandas 过滤具有多个值的单元格中的字符串

使用 pyspark/pandas 使用列名的模式匹配对具有不同列名的多个列值求和

Pandas 将具有多个值的行数据合并到列的 Python 列表中

FillNaN 具有多个条件并在 Pandas 中使用 n-1 和 n+2 值