代码之家  ›  专栏  ›  技术社区  ›  ChesuCR Ayansplatt

如何有效地将值(从CSV文件)映射到Pandas数据帧?

  •  0
  • ChesuCR Ayansplatt  · 技术社区  · 6 年前

    我有这样一个CSV:

    enter image description here

    其中第一列可以有间隙,但第二列和第三列的值中间没有间隙。

    列的值 TO_REPLACE 应替换为列中的值 VALUE_TO_COPY 前提是其单元格的内容与列的单元格值一致 TO_SEARCH . 结果应该是:

    enter image description here

    我写了一个剧本:

    import pandas as pd
    import numpy as np
    
    df = pd.read_csv(
        filepath_or_buffer='mapping_test.csv',
        delimiter=',',
        dtype=str
    )
    
    to_replace = df['TO_REPLACE'].copy()
    result = df['TO_REPLACE'].copy()
    
    df = df.set_index('TO_SEARCH')
    df.dropna(
        how='all',
        inplace=True
    )
    
    del df['TO_REPLACE']
    
    for key, value in to_replace.iteritems():
        try:
            result[key] = df.loc[value, 'VALUE_TO_COPY']
        except:
            print('ERROR, not found KEY: {}'.format(key))
    
    result_df = pd.DataFrame(
        data={
            'TO_REPLACE': result,
            'VALUE_TO_COPY': list(df['VALUE_TO_COPY']) + [np.nan] * (len(result) - df['VALUE_TO_COPY'].size),
            'TO_SEARCH': list(df.index) + [np.nan] * (len(result) - df['VALUE_TO_COPY'].size),
        }, 
        columns=['TO_REPLACE','VALUE_TO_COPY','TO_SEARCH']  # to preserve the column order
    )
    
    result_df.to_csv(
        path_or_buf='mapping_result.csv',
        index=False
    )
    

    我在代码中所做的:

    1. 我将CSV中的数据读入数据框

    2. 我把数据框分成两部分。一方面我储存 替换 作为一个系列,另一方面是一个带有列的数据框架 值复制 搜索 . 我用 搜索 作为此数据帧的索引。

    3. 我在列上迭代 替换 以便在列中找到值 搜索 . 如果值不一致,我就保留原来的值。

    4. 我用替换的值再次构建一个数据帧,并将其存储到CSV文件中。

    但效率不高。我需要经常映射成千上万的值,这就是为什么我需要一个更有效的代码。有什么办法来增强我的代码吗?

    也许我可以用这些方法 map (对于系列), apply applymap (用于DF)。至少我放弃了 应用 因为它一次运行一整排 苹果酱 操作整个数据帧。也许最有用的是 地图 ,但我认为它会像手动那样遍历所有值。我考虑过的另一个可能的选择是 replace ,但我读过 地图 更快。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Trenton McKinney ivirshup    6 年前

    2018-09-03_map_with_pandas.ipynb

    import pandas as pd
    df = pd.read_csv('data/RBefh.csv', dtype=str)
    keys = list(df['to_search'].dropna())
    values = list(df['value_to_copy'].dropna())
    map_values = dict(zip(keys, values))
    mapper = df.to_replace.isin(map_values)
    df.loc[mapper, 'to_replace'] = df.loc[mapper, 'to_replace'].apply(lambda row: map_values[row])
    df.fillna('', inplace=True)
    

    输出:

                to_replace       value_to_copy   to_search
    0   __import__.value_1  __import__.value_1  2012000401
    1   __import__.value_1  __import__.value_2  2012000501
    2   __import__.value_1  __import__.value_3  2012000601
    3   __import__.value_2  __import__.value_4  2012000603
    4   __import__.value_2  __import__.value_5  2012000604
    5   __import__.value_2  __import__.value_6  2012000605
    6                       __import__.value_7  2012000606
    7   __import__.value_2  __import__.value_8  2012000607
    8   __import__.value_2  __import__.value_9  2012000608
    9   __import__.value_2  __import__.value_10 2012000609
    10                      __import__.value_11 2012000610
    11  __import__.value_2  __import__.value_12 2012000701
    12  __import__.value_2  __import__.value_13 2012000702
    13  __import__.value_3      
    14  __import__.value_4      
    15  __import__.value_5      
    16  __import__.value_6      
    17  __import__.value_7      
    18  __import__.value_8      
    19  __import__.value_9      
    20  __import__.value_10     
    21  __import__.value_11     
    22  __import__.value_12     
    23  __import__.value_12     
    24  __import__.value_12     
    25  __import__.value_12     
    26  __import__.value_12     
    27  __import__.value_12     
    28  __import__.value_12     
    29  2012999999
    
        2
  •  0
  •   Schalton    6 年前

    我不会用熊猫。

    我会把它们从发电机里读入字典。

    使用此项访问数据:

    def read_file(fullname):
        with open(fullname) as f:
            for index, line in enumerate(f):
                if index == 0:
                    header_line = line
                else:
                    yield header_line, line
    
    myFile = read_file(r"Path/To/Your/File")
    
    for header, line in myFile:
        data = dict(zip(header.split(" "), line.split(" ")))
        .....
    

    并创建 crosswalk_dict /在遍历生成器时填充的几个crosswalk命令。