Как эффективно отобразить значения (из файла CSV) с помощью Pandas DataFrame? - PullRequest
0 голосов
/ 03 сентября 2018

У меня есть 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 в DataFrame

  2. Я разделил DataFrame на две части. С одной стороны, я храню TO_REPLACE как Series, а с другой стороны - DataFrame со столбцами VALUE_TO_COPY и TO_SEARCH. Я использую TO_SEARCH в качестве индекса этого DataFrame.

  3. Я перебираю столбец TO_REPLACE, чтобы найти значения в столбце TO_SEARCH. Если значения не совпадают, я сохраняю старое значение.

  4. Я снова строю DataFrame с замененными значениями и сохраняю его в файле CSV.

Но это не очень эффективно. Мне нужно очень часто отображать тысячи значений, поэтому мне нужен более эффективный код. Есть идеи по улучшению моего кода?

Может быть, я мог бы использовать методы map (для серии), apply или applymap (для DF). По крайней мере, я отбросил apply, потому что он работает на всю строку за раз, а applymap работает на весь DataFrame. Возможно, наиболее полезным является map, но я думаю, что он перебирает все значения, как я делал вручную. Другой возможный вариант, который я рассмотрел, - это метод replace, но я прочитал, что map быстрее.

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

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
0 голосов
/ 03 сентября 2018

Я бы не использовал панд.

Я бы прочитал их в словарь из генератора.

Используйте это для доступа к данным:

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 / несколько указаний для пешеходного перехода, которые вы заполняете при прохождении через генератор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...