匹配两个日期范围和长度不同的数据集
我有两个csv文件,它们的日期格式和长度都不一样。
首先,我加载这两个文件:
frameA = pd.read_csv("fileA.csv", dtype=str, delimiter=";", skiprows = None)
文件A有102216行和3列,最后一行的时间是01.07.2012 00:00
。日期和时间在同一列里。文件的开头看起来是这样的:
Date Buy Sell
0 01.08.2009 00:15 0 0
1 01.08.2009 00:30 0 0
2 01.08.2009 00:45 0 0
3 01.08.2009 01:00 0 0
4 01.08.2009 01:15 0 0
.
frameB = pd.read_csv("fileB.csv", dtype=str, delimiter=";", skiprows = None)
文件B有92762行和4列,最后一行的时间是22.07.2012 00:00
。日期和时间是分开的。文件的开头看起来是这样的:
Date Time Buy Sell
0 01.08.2009 01:00 0 0
1 01.08.2009 02:00 0 0
2 01.08.2009 03:00 0 0
3 01.08.2009 04:00 0 10
4 01.08.2009 05:00 0 32
我该如何将这些数据匹配起来呢:
Buy A Sell A Buy B Sell B
0 01.08.2009 00:15 0 0 0 0
1 01.08.2009 00:30 0 0 0 0
两个文件的开始和结束日期都要相同,并且时间间隔要是15分钟。
我该怎么做呢?我应该先做什么?
2 个回答
你还可以把日期设置为索引:
正如上面的回答所说,第一步是把它们解析成相同的格式。
frameA = pd.read_csv("fileA.csv", dtype=str, delimiter=";", skiprows = None, parse_dates=['Date'])
frameB = pd.read_csv("fileB.csv", dtype=str, delimiter=";", skiprows = None, parse_dates=[['Date','Time']])
在把数据放进数组后,如上所示,我们可以把索引设置为数据,以便于合并:
frameA.index = frameA['Date']
frameB.index = frameB['Date']
这样,它们就会在完全相同的索引上合并,而且因为它们有相似的列('买入','卖出'),我们需要为合并指定后缀:
merge = frameA.join(frameB, lsuffix = ' A', rsuffix = ' B')
结果看起来会是这样的。
Buy A Sell A Buy B Sell B
0 01.08.2009 00:15 0 0 0 0
1 01.08.2009 00:30 0 0 0 0
这种方法的好处是,如果你的第二个数据集('买入 B','卖出 B')缺少第一个数据集中存在的时间,合并仍然可以正常工作,你不会把数据错误地分配到不正确的时间上。假设我们有一个从1到10000的任意数字索引,而第二个数据框只包含1到9997的索引,这样就会导致偏移,然后我们会错误地把值分配到错误的索引上。
在这里,只要指导合并的数据框比第二个数据框长,我们就不会丢失任何数据,也不会把数据错误地分配到错误的索引上。
举个例子:
if len(frameA.index) >= len(frameB.index):
merge = frameA.join(frameB)
else:
print 'Missing Values, define your own function here'
quit()
编辑:
确保所有数据都能被报告,不管它是否出现在两个列中的另一种方法是定义一个新的数据框,里面包含两个数据框中都有的独特日期列表,并用这个来指导合并。
例如,
unique_index = sorted(list(set(frameA.index.tolist() + frameB.index.tolist())))
通过把两个索引列表相加,转成集合,再转回列表来定义一个独特的索引。集合会去掉所有重复的值,所以你会得到一个独特的列表,而且这个列表是排序的,因为集合是无序的。
然后,你就可以合并数据框:
merge = pd.DataFrame(index = unique_index)
merge = merge.join(frameA)
merge = merge.join(frameB, lsuffix = ' A', rsuffix = ' B')
只要确保导出时索引是开启的,或者把索引重新定义为一列(导出到csv或excel表格时,索引默认是开启的,除非你关闭它,所以一定要确保没有设置index = False)。
这样,任何在'买入 A','卖出 A'列中缺失但在'买入 B','卖出 B'中存在的数据会显示为'nan',同样,'买入 B','卖出 B'中缺失但在'买入 A','卖出 A'中存在的数据也会显示为'nan'。
好的,首先要确保第一个数据框(df)的时间数据类型是日期时间:
frameA = pd.read_csv("fileA.csv", dtype=str, delimiter=";", skiprows = None, parse_dates=['Date'])
然后对于另一个数据框:
frameB = pd.read_csv("fileB.csv", dtype=str, delimiter=";", skiprows = None, parse_dates=[['Date','Time']])
接下来,我会像这样重置第一个数据框的分钟值:
In [149]:
df['Date'] = df['Date'].apply(lambda x: x.replace(minute=0))
df
Out[149]:
Date Buy Sell
index
0 2009-01-08 04:00:00 0 0
1 2009-01-08 04:00:00 0 0
2 2009-01-08 04:00:00 0 0
3 2009-01-08 05:00:00 0 0
4 2009-01-08 05:00:00 0 0
现在我们可以把这两个数据框合并在一起:
In [150]:
merged = df.merge(df1, left_on=['Date'], right_on=['Date_Time'], how='left',suffixes=[' A', ' B'])
merged
Out[150]:
Date Buy A Sell A Date_Time Buy B Sell B
0 2009-01-08 04:00:00 0 0 2009-01-08 04:00:00 0 10
1 2009-01-08 04:00:00 0 0 2009-01-08 04:00:00 0 10
2 2009-01-08 04:00:00 0 0 2009-01-08 04:00:00 0 10
3 2009-01-08 05:00:00 0 0 2009-01-08 05:00:00 0 32
4 2009-01-08 05:00:00 0 0 2009-01-08 05:00:00 0 32
显然,你需要把 df
和 df1
替换成你自己用的 frameA
和 frameB
。