场景:根据以前的一些问题,我现在有一个代码可以产生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
等等。请记住,某些标识符在两个数据框中都有相同日期的数据(出价/提问),有些只有其中一个标识符。
答案 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