匹配来自2个pandas数据帧的数据

时间:2017-07-21 12:29:12

标签: python pandas dataframe

场景:根据以前的一些问题,我现在有一个代码可以产生2个数据帧(买/卖)。

我要做的是:这两个数据框的日期为列标题,标识符为行索引,其他所有内容的数字值。我希望将日期,标识符,出价和问题以及输出与txt相匹配,格式如下:

date 1    identifier 1    bid    ask
date 1    identifier 2    bid    ask
date 1    identifier 3    bid    ask
date 2    identifier 1    bid    ask
date 2    identifier 2    bid    ask
date 2    identifier 4    bid    ask
date 3    identifier 2    bid    ask
date 2    identifier 3    bid    ask

等等。

Obs1:并非所有日期都包含所有标识符的值(有些是NaN)。

Obs2:我已经尝试(在我的代码的早期版本中)拥有数据框列表或只有两个数据框(出价和询问),但我一直遇到多个问题(例如:我得到未知值格式或超时),所以我决定将我的源文件分成两组。

问题:我无法正确匹配数据(如vlookup)

问题1:我做错了什么?还有更好的方法吗?

Obs3:我目前正在尝试使用multiindex创建一个更高级别为(bid / ask)的3d数据框。我也尝试过使用pandas的series.map函数来做一些" vlookup"在数据帧之间,但这并不是非常有效。

当前代码:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import glob, os
import datetime as dt
from datetime import datetime
import matplotlib as mpl
from openpyxl import load_workbook
import sys


directory = os.path.join("C:\\","Users\\DGMS\\Desktop\\final 2\\run 1 test")        
dfbid = pd.DataFrame()
dfask = pd.DataFrame()

b = pd.DataFrame()
a = pd.DataFrame()

for root,dirs,files in os.walk(directory):

    for file in files:

        f = os.path.join(root, file)

        wb = load_workbook(f)

        print (f)
        for sheet in wb.worksheets:

            if sheet.title == "Bid":

                a = pd.read_excel(f, "Bid")

                for i in range(1,len(a.columns)):
                    a.columns.values[i] = pd.to_datetime(a.columns.values[i])

                dfbid = pd.concat([dfbid, a])
                print ('bid done')

            elif sheet.title == "Ask":

                b = pd.read_excel(f, "Ask")

                for i in range(1,len(b.columns)):
                    b.columns.values[i] = pd.to_datetime(b.columns.values[i])

                dfask = pd.concat([dfask, b])
                print ('ask done')


parts = {'Bid': dfbid, 'Ask': dfask}

finalresult = pd.concat(parts)

这是我的第一个数据框之一(问):

                01/01/2010   02/01/2010   03/01/2010
AT0000383864      160.614       161.1436    161.1532
AT0000385745      109.3122      109.3144    109.3068
AT0000386115      117.7972      118.0388    118.051
AT0000A001X2      119.7004      120.0058    120.031
AT0000A04967      152.8196      153.7868    153.792

这是我的第二个数据框(出价)之一的片段:

                01/01/2010   02/01/2010   03/01/2010
AT0000383864     161.038      161.5676    161.5772
AT0000385745     109.4322     109.4344    109.4268
AT0000386115     118.0202     118.2618    118.274
AT0000A001X2     119.8284     120.1338    120.159

我想要的是什么(输出到txt):

AT0000383864    01/01/2010    161.038     160.614
AT0000383864    02/01/2010    161.5676    161.1436
AT0000383864    03/01/2010    161.5772    161.1532
AT0000385745    01/01/2010    109.4322    109.3122

等等。请记住,某些标识符在两个数据框中都有相同日期的数据(出价/提问),有些只有其中一个标识符。

1 个答案:

答案 0 :(得分:2)

您可以融化数据框以将列重新打开成行,然后使用项目和日期合并两个数据框。

以下是组装您发布的数据框的准备工作:

import pandas as pd

ask_str = '''AT0000383864      160.614       161.1436    161.1532
AT0000385745      109.3122      109.3144    109.3068
AT0000386115      117.7972      118.0388    118.051
AT0000A001X2      119.7004      120.0058    120.031
AT0000A04967      152.8196      153.7868    153.792'''

bid_str = '''AT0000383864     161.038      161.5676    161.5772
AT0000385745     109.4322     109.4344    109.4268
AT0000386115     118.0202     118.2618    118.274
AT0000A001X2     119.8284     120.1338    120.159'''

ask_data = [line.split() for line in ask_str.split('\n')]
bid_data = [line.split() for line in bid_str.split('\n')]

ask_df = pd.DataFrame(ask_data, columns='item 01/01/2010 02/01/2010 03/01/2010'.split())
bid_df = pd.DataFrame(bid_data, columns='item 01/01/2010 02/01/2010 03/01/2010'.split())

如果我们使用pd.melt,我们可以获取列标题并将其转换为新列的值。例如,以下操作将item保留为列,使用其他列名称(日期)作为名为date的新列的值,并将值列重命名为ask

pd.melt(ask_df, id_vars='item', var_name='date', value_name='ask')

#returns:
            item        date       ask
0   AT0000383864  01/01/2010   160.614
1   AT0000385745  01/01/2010  109.3122
2   AT0000386115  01/01/2010  117.7972
3   AT0000A001X2  01/01/2010  119.7004
4   AT0000A04967  01/01/2010  152.8196
5   AT0000383864  02/01/2010  161.1436
6   AT0000385745  02/01/2010  109.3144
7   AT0000386115  02/01/2010  118.0388
8   AT0000A001X2  02/01/2010  120.0058
9   AT0000A04967  02/01/2010  153.7868
10  AT0000383864  03/01/2010  161.1532
11  AT0000385745  03/01/2010  109.3068
12  AT0000386115  03/01/2010   118.051
13  AT0000A001X2  03/01/2010   120.031
14  AT0000A04967  03/01/2010   153.792

这是我们加入两个数据帧所需的数据形式。我们将两个数据帧融合以取消它们,然后将它们合并到适当的列上。

ab_df = pd.merge(pd.melt(ask_df, id_vars='item', var_name='date', value_name='ask'),
                 pd.melt(bid_df, id_vars='item', var_name='date', value_name='bid'),
                 how='inner',
                 on=['item','date'])

现在我们可以按项目排序,然后按日期

排序
ab_df.sort_values(['item', 'date'])
#returns:
            item        date       ask       bid
0   AT0000383864  01/01/2010   160.614   161.038
4   AT0000383864  02/01/2010  161.1436  161.5676
8   AT0000383864  03/01/2010  161.1532  161.5772
1   AT0000385745  01/01/2010  109.3122  109.4322
5   AT0000385745  02/01/2010  109.3144  109.4344
9   AT0000385745  03/01/2010  109.3068  109.4268
2   AT0000386115  01/01/2010  117.7972  118.0202
6   AT0000386115  02/01/2010  118.0388  118.2618
10  AT0000386115  03/01/2010   118.051   118.274
3   AT0000A001X2  01/01/2010  119.7004  119.8284
7   AT0000A001X2  02/01/2010  120.0058  120.1338
11  AT0000A001X2  03/01/2010   120.031   120.159