如何使用两组变量取消堆叠pandas数据帧

时间:2015-11-02 17:55:35

标签: python pandas

我有一张看起来像这样的桌子。从CSV文件中读取,所以没有级别,没有花哨的索引等等。

ID  date1      amount1    date2        amount2
x   15/1/2015   100        15/1/2016   80

我的实际文件是最新的5和5。 我怎样才能将其转换为:

ID  date       amount
x   15/1/2015  100
x   15/1/2016   80

如果我只有一个变量,我会使用pandas.melt(),但有两个变量,我真的不知道如何快速完成。

我可以手动导出到内存中的sqlite3数据库并进行联合。在大熊猫中使用联合会更烦人,因为与SQL不同,它要求所有字段名称都相同,所以在大熊猫中我必须创建一个临时数据帧并重命名所有字段:date1和amount1的数据帧,将字段重命名为日期和金额,然后对所有其他事件执行相同操作,然后才能执行pandas.concat。

有什么建议吗?谢谢!

2 个答案:

答案 0 :(得分:4)

这是一种方式:

>>> pandas.concat(
...     [pandas.melt(x, id_vars='ID', value_vars=x.columns[1::2].tolist(), value_name='date'),
...      pandas.melt(x, value_vars=x.columns[2::2].tolist(), value_name='amount')
...     ],
...     axis=1
... ).drop('variable', axis=1)
  ID       date  amount
0  x  15/1/2015     100
1  x  15/1/2016      80

这个想法是做两个熔化,每组一个,然后连接它们。这假设两种列按交替顺序排列,以便columns[1::2]columns[2::2]正确选择它们。如果没有,您必须修改其中的一部分以选择所需的列。

你也可以使用鲜为人知的lreshape

来做到这一点
>>> pandas.lreshape(x, {'date': x.columns[1::2], 'amount': x.columns[2::2]})
  ID       date  amount
0  x  15/1/2015     100
1  x  15/1/2016      80

然而,lreshape并没有真正记录在案,并且不清楚它是否应该被使用。

答案 1 :(得分:1)

如果我认为列总是重复,一个简单的技巧就可以提供你想要的解决方案。

诀窍在于列出一起列的列表,然后根据需要在主列表上循环。它确实涉及每次循环运行时调用pd.DataFrame()。我现在有点紧迫的时间找到避免这种情况的方法。但它确实像您期望的那样工作,对于一个小文件,您不应该有任何问题(即运行时)。

In [1]: columns = [['date1', 'amount1'], ['date2', 'amount2'], ...]

In [2]: df_clean = pd.DataFrame(columns=['date', 'amount'])
        for cols in columns:
            df_clean = df_clean.append(pd.DataFrame(df.loc[:,cols].values,
                                                    columns=['date', 'amount']),
                                       ignore_index=True)
df_clean
Out[2]:     date        amount
        0   15/1/2015   100
        1   15/1/2016   80

关于这一点的巧妙之处在于它只在DataFrame上运行一次,选择它循环的列下的所有行。所以如果你有5个列对,那么' n'在它下面的行,循环只运行5次。对于每次运行,它将附加所有' n'列下方的行到干净的DataFrame,以提供一致的结果。然后,您可以消除任何NaN值并按日期排序,或者对干净的DF执行任何操作。

您怎么看?这会创建一个内存中的sqlite3数据库吗?