• Python学习笔记:给定邮编,判断区域


    一、背景

    给定一个维表,如下:

    区域	编码范围
    N0	1000-1935, 2000-2079, 2085-2107
    GF	2250-2263
    WG	2500-2507, 2515-2532
    NC	2282-2310
    BR	3350, 3353-3356
    V2	2648, 2715, 2717-2719
    V3	3689-3690
    Q5	4225
    

    每一个区域编码,都会包含多个不同、不一定连续的编码,如编码范围列所示,要求给定一个编码值,求所对应的区域。

    二、思路

    1.思路一

    将编码范围进行拆分,构造出每一个编码与区域的键值对,生成一个字典,再进行值的查找。

    实现最终效果如下:

    0	N0	1000
    1	N0	1001
    2	N0	1002
    3	N0	1003
    4	N0	1004
    5	N0	1005
    ......
    9158	NT2	901
    9159	NT2	902
    9160	NT2	903
    9161	NT2	904
    9162	NT2	905
    

    再通过列值的查找,即可返回对应的区域。

    此方法计算量较大,需要将每一个编码跨度的每一个取值均生成出来。

    2.思路二

    后续优化的时候,考虑其实无须将每一个编码都生成 duck不必!,只需要判断编码是否连续。

    连续的编码,取最小值(下限)、最大值(上限)构造两列。

    非连续编码,令最大值=最小值。

    如下所示:

        区域 Min_value Max_value
    0   N0      1000      1935
    1   N0      2000      2079
    2   N0      2085      2107
    3   GF      2250      2263
    4   WG      2500      2507
    5   WG      2515      2532
    6   NC      2282      2310
    7   BR      3350      3350
    8   BR      3353      3356
    9   V2      2648      2648
    10  V2      2715      2715
    11  V2      2717      2719
    12  V3      3689      3690
    13  Q5      4225      4225
    

    最后通过判断:Min_value <= 编码 <= Max_value 即可。

    3.思路三

    类似于思路二,只是中间直接用 reset_index() + stack() 直接堆叠实现。

    三、实操

    1.思路一实操

    # 追加 构造字典方式
    import os
    import pandas as pd
    os.chdir(r'C:\Users\111\Desktop')
    
    # 读取原始表
    df = pd.read_excel(r'df.xlsx')
    result = []
    
    # 按行循环 效率低
    for i in range(len(df)):
        # 每一行
        print(i)
        # 判断是否包括逗号
        if ',' not in str(df.loc[i, '编码范围']):
            # 判断是否包括横线
            if '-' not in str(df.loc[i, '编码范围']):
                # 不包括的直接追加结果表
                result.append([df.loc[i, '区域'], df.loc[i, '编码范围']])
            else:
                # 没逗号有横线的 切分为最小值,最大值,生成追加结果表
                a, b = [int(x) for x in df.loc[i, '编码范围'].split('-')]
                for x in range(a, b+1):
                    # print(x)
                    result.append([df.loc[i, '区域'], x])
        # 有逗号
        else:
            for y in df.loc[i, '编码范围'].split(','):
                # print(y)
                # 有逗号 没横线 直接追加
                if '-' not in y:
                    result.append([df.loc[i, '区域'], y])
                    # print(y)
                else:
                    #  有逗号有横线
                    c, d = [int(x) for x in y.split('-')]
                    # print(c, d)
                    for x in range(c, d+1):
                        # print(x)
                        result.append([df.loc[i, '区域'], x])
                    
    result = pd.DataFrame(result, columns=['区域', '编码范围'])
    result['编码范围'] = result['编码范围'].astype(int)
    result.to_excel(r'result.xlsx')
    result.sort_values(by='编码范围', inplace=True)
    result.reset_index(drop=True, inplace=True)
    result
    '''
          区域  编码范围
    0     N0  1000
    1     N0  1001
    2     N0  1002
    3     N0  1003
    4     N0  1004
      ..   ...
    1116  BR  3355
    1117  BR  3356
    1118  V3  3689
    1119  V3  3690
    1120  Q5  4225
    
    [1121 rows x 2 columns]
    '''
    

    2.思路二实操

    • 构造编码范围上下限
    import os
    import pandas as pd
    os.chdir(r'C:\Users\111\Desktop')
    
    # 读取数据
    df = pd.read_excel(r'df.xlsx')
    # 如果包含逗号则进行分列
    df['编码范围'] = df['编码范围'].apply(lambda x: x.split(',') if ',' in str(x) else x)
    # 炸裂 列转多行
    df = df.explode('编码范围').reset_index(drop=True)
    # 去除头尾多余的空格
    df['编码范围'] = df['编码范围'].apply(lambda x: str(x).strip())
    # 按横线切割再展开 构造最小值、最大值列
    df[['Min_value', 'Max_value']] = df['编码范围'].str.split('-', expand=True).rename(columns={0:'Min_value', 1:'Max_value'})
    # 最大值列为空填充为最小值
    df.loc[df['Max_value'].isnull(), 'Max_value'] = df.loc[df['Max_value'].isnull(), 'Min_value']
    # 转换为数值
    df['Min_value'] = df['Min_value'].astype(int)
    df['Max_value'] = df['Max_value'].astype(int)
    # 查看类型
    df.dtypes
    '''
    区域           object
    编码范围         object
    Min_value     int32
    Max_value     int32
    dtype: object
    '''
    #### 输出 ####
    '''
        区域       编码范围 Min_value Max_value
    0   N0  1000-1935      1000      1935
    1   N0  2000-2079      2000      2079
    2   N0  2085-2107      2085      2107
    3   GF  2250-2263      2250      2263
    4   WG  2500-2507      2500      2507
    5   WG  2515-2532      2515      2532
    6   NC  2282-2310      2282      2310
    7   BR       3350      3350      3350
    8   BR  3353-3356      3353      3356
    9   V2       2648      2648      2648
    10  V2       2715      2715      2715
    11  V2  2717-2719      2717      2719
    12  V3  3689-3690      3689      3690
    13  Q5       4225      4225      4225
    '''
    
    • 构造函数判断取值
    def find_email(df, n):
        '''
        df    展开的维表
        n     待查找的编码
        '''
        is_or_not = (df['Min_value'] <= n) & (df['Max_value'] >= n)
        return df.loc[is_or_not, '区域'].values[0]
    
    result = find_email(df, 2718)
    print(f'所查找的邮编归属区域为:{result}')
    # 所查找的邮编归属区域为:V2
    

    3.思路三实操

    # 直接堆叠
    df = pd.read_excel(r'df.xlsx')
    df.set_index('区域', inplace=True)
    df['编码范围'] = df['编码范围'].astype(str)
    df = df['编码范围'].str.split(',', expand=True)
    df = df.stack().reset_index()[['区域', 0]].rename(columns={0: 'Code_min_max'})
    df.set_index('区域', inplace=True)
    df = df['Code_min_max'].str.split('-', expand=True).rename(columns={0:'Min', 1:'Max'}).reset_index()
    df.loc[df['Max'].isnull(), 'Max'] = df.loc[df['Max'].isnull(), 'Min']
    
    x = 2718
    y = df.loc[(df['Min'].astype(int) < x) & ( df['Max'].astype(int) > x), '区域'].values[0]
    
  • 相关阅读:
    反射工具类
    序列化反序列化工具类
    开发SCM系统笔记001
    卸载Oracle
    log4j日志级别
    类加载器与methodinterceptor接口
    hibernate 查询、二级缓存、连接池
    Hibernate缓存、组件、继承映射
    Hibernate映射1
    Hibernate配置文件
  • 原文地址:https://www.cnblogs.com/hider/p/15853100.html
Copyright © 2020-2023  润新知