Python/pandas数据帧中的数值模糊比较连接

2024-06-24 13:51:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我有四张航空公司时刻表。我实际上没有列PK,但我把它放在那里,这样我可以更容易地参考航班。我把它们放进去了pd.数据帧马上。你知道吗

表1。草稿#1

MarketID  Origin Dest FltNum  DepCentral  ArrCentral  PK
1DFWSJC   DFW    SJC  111     0700        1035        A
2DFWSJC   DFW    SJC  222     2035        2410        B

表2。草稿#2

MarketID  Origin Dest FltNum  DepCentral  ArrCentral  PK
1DFWSJC   DFW    SJC  111     0700        1030        A
2DFWSJC   DFW    SJC  222     2040        2410        B

表3。草稿#3

MarketID  Origin Dest FltNum  DepCentral  ArrCentral  PK
1DFWSJC   DFW    SJC  444     0645        1015        A
2DFWSJC   DFW    SJC  555     1300        1630        X
3DFWSJC   DFW    SJC  666     2040        2410        B

表4。最终时间表

MarketID  Origin Dest FltNum  DepCentral  ArrCentral  PK
1DFWSJC   DFW    SJC  444     0645        1015        A
2DFWSJC   DFW    SJC  666     2040        2415        B

我基本上想跟踪草稿1中的每一个航班,也就是最后的时刻表,看看它们是如何在生产中被修改的。但我也在试图追踪每个表中每个航班的变化。本质上,它是一个内部连接,我有DepCentral\u Draft1、DepCentral\u Draft2等列

有了这个,我可以看出在草案1和草案2之间,A航班的到达时间提前了5分钟。在草案2和草案3之间,A航班的起飞和到达时间提前了15分钟。等等

MarketID很接近,但在草稿2和草稿3之间,他们插入了一个航班,并重新标记了MarketID(按起飞时间排序)。他们似乎在草案2和草案3之间,以及草案3和最终版本之间,非常随意地增减航班,所以我不能依赖市场。你知道吗

FltNum也很不一致。在草稿1和草稿2之间,它们是匹配的,但是草稿3和草稿4之间,它们似乎随机地在草稿3之后重新标记航班号。你知道吗

作为一个人,我可以看出表3中的2DFWSJC既不是航班a也不是航班B,因为它的出发/到达时间有多不同。当我加入MarketID时,它认为B航班将从2040移到1300(这就是我注意到这些插入的原因)。你知道吗

我无法连接起点、目的地、出发或到达时间和匹配,因为它们被稍微移动,所以它们不完全匹配。我见过用字符串做的模糊比较,但我没见过用数字做这样的比较。你知道吗

就像把B航班定义为

Origin     = DFW  
Dest       = SJC   
DepCentral = ~2035 
ArrCentral = ~2410    

在这里,我可以定义距离有多近,或者它会自动意识到2040年比1300年更接近2035年,如果可能的话,加入。你知道吗

这是我编写的原始函数,用于查找原始计划和新计划之间的差异。你知道吗

def schdChanges(base, new):
merged = pd.merge(base, new, on = ['MktSegID'])

diffDf = pd.DataFrame()

diffDf['MktSegID'] = merged['MktSegID']
diffDf['Cdep'] = merged['Cdep_y'] - merged['Cdep_x']
diffDf['Carr'] = merged['Carr_y'] - merged['Carr_x']
diffDf['Block'] = merged['Block_y'] - merged['Block_x']
diffDf['Turn'] = merged['Turn_y'] - merged['Turn_x']

return diffDf 

编辑。我遇到的其他解决方案是确定市场容量(如DFW-SJC)发生了哪些变化,并只关注这些变化。你知道吗

方向-起点+终点

Draft1Cap = Draft1.groupby('DirMkt')['MktSegID'].nunique()
FinalCap  = Final.groupby( 'DirMkt')['MktSegID'].nunique()

FinalCap.subtract(Draft1Cap, fill_value = 0)[FinalCap.subtract(Draft1Cap, fill_value = 0) != 0]  

所以现在我已经确定哪些已经改变了。我以前的函数适用于除这些以外的所有对象。你知道吗

利用这一点,我决定从时间表中删除哪些市场,因为它们在草案和最终版本中都不存在

def returnNotMatches(a, b):
    return [[x for x in a if x not in b], [x for x in b if x not in a]]  

returnNotMatches(set(Draft1['DirMkt'].unique()), set(Final['DirMkt'].unique())) 

所以基本上,我需要知道的是,当一个航班被添加时,相对于市场上的其他航班,它被添加到了哪里?你知道吗


Tags: originmergeddest草稿航班pk草案sjc
1条回答
网友
1楼 · 发布于 2024-06-24 13:51:41

你有6列。让我们按它们在这种情况下有多有用来细分它们。你知道吗

MarketIDFltNum可以任意更改,这样对我们没有帮助。 OriginDest我想肯定是一样的,不能改变,所以我们来检查一下 DepCentralArrCentral是最重要的,每个问题陈述最多可以更改50分钟。你知道吗

您有一些复杂的业务逻辑,因此可能没有简单的解决方案。所以这里的乐趣来了,编码的东西来处理这个逻辑!你知道吗

此程序将查找匹配项,我将由您决定如何获得您想要的输出

import pandas as pd

如果你有日期,或者确定你在23:55不会有需要与00:04匹配的东西,那么你可以简化或替换这个逻辑

def time_change(old_time, new_time):
    old_hrs, new_hrs = int(old_time[0:2]), int(new_time[0:2])
    old_mins, new_mins = int(old_time[2:]), int(new_time[2:])

    old_total = 60 * old_hrs + old_mins
    new_total = 60 * new_hrs + new_mins

    # note, this may make incorrect assumptions since we don't have the day. 
    # If you have the day in your actual data, there are better ways of comparing the times
    return abs((new_total - old_total)) % (24 * 60)

现在,到问题的核心,检查匹配。你列出了你想要的,所以这只是一些逻辑来实现它。此函数接受任意两行进行比较。你知道吗

def check_match(old, new):
    #["MarketID", "Origin", "Dest", "FltNum", "DepCentral", "ArrCentral"]
    if old['Origin'] != new['Origin']:
        return False, "", ""
    if old['Dest'] != new['Dest']:
        return False, "", ""
    total_time_change = time_change(old["DepCentral"], new["DepCentral"]) + \
        time_change(old["ArrCentral"], new["ArrCentral"])
    if abs(total_time_change) <= 50:
        return True, total_time_change, "other fields that changed"
    else:
        return False, "", ""

循环遍历新旧表中的所有行并进行比较。根据你提到的数据的大小,查看所有内容应该是可以的。你知道吗

def compare_tables(old, new_df):
    if 'PK' not in old.columns:
        # use the current index as the starting PK
        old['PK'] = old.index
    for _, old_row in old.iterrows():
        print("Looking at row:")
        print(old_row.T)
        pk = old_row['PK']
        best_match = None
        best_match_time_change = float('inf')
        for _, new_row in new_df.iterrows():
            is_match, time_change, old_changes = check_match(old_row, new_row)
            if is_match and (time_change < best_match_time_change):
                best_match_time_change = time_change
                best_match = new_row
        print("The best match is:")
        if best_match is not None:
            print(best_match.T, best_match_time_change)
        else:
            print("no matches found")
        print()
        print()

遍历所有表对:

all_tables = [table_1, table_2, table_3, table_4]
for old, new_df in zip(all_tables, all_tables[1:]):
    compare_tables(old, new_df)

相关问题 更多 >