2015-11-02 74 views
1

我有一张看起来像这样的表。从CSV文件中读取,所以没有水平,没有花哨的索引等如何用两组变量弹出一个熊猫数据框

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

实际的文件我已经上升到date5和金额5 我怎样才能将其转换为:

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

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

我可以手动导出到内存中的sqlite3数据库,并做一个联合。在熊猫中进行联合更麻烦,因为与SQL不同,它需要所有字段名称相同,因此在熊猫中,我必须创建一个临时数据框并重命名所有字段:date1和amount1的数据帧,将字段的日期和金额,然后对所有其他事件做同样的事情,只有这样我才能做pandas.concat。

有什么建议吗?谢谢!

回答

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数据库?

3

这里有一种方法:

>>> 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 

的想法是做两个熔体,每个组列,然后CONCAT他们。这假设这两种列交替排列,以便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是不是真的记录,如果它应该使用目前还不清楚。

+0

非常有用,谢谢!是concat()与axis = 1相当于merge()? –

+0

@Pythonistaan​​onymous:我认为'合并'比较灵活,允许不同类型的连接。 'concat'只是将多个DF彼此堆放在一起。 – BrenBarn