我有一张看起来像这样的桌子。从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。
有什么建议吗?谢谢!
答案 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数据库吗?