Pandas объединяет столбцы в некоторых строках на основе значения в другом столбце для обработки неоднородных CSV-данных

#python #pandas #dataframe #csv

#python #pandas #dataframe #csv

Вопрос:

У меня есть файл csv, в котором содержится неравномерное количество столбцов. В одном столбце указано число, которое указывает, сколько дополнительных столбцов содержит эта строка. Этот столбец «num_servers» и является целым числом. За этим столбцом следует один сервер и один столбец портов для каждого num_server, т.Е. «host_0», «port_0», «host_1», «port_1» для num_server = 2.

Я хочу объединить эти столбцы, в которых есть данные, т.Е. Сервер, порт и заполнить None / Nan, где их нет, чтобы у меня был единый фрейм данных, в котором только столбцы в середине содержат Nones, и в итоге получился фрейм данных.

Пример csv:

 sym1,exch,3,server_a,port_a,server_a,port_b,server_f,port_f,info1,info2,info3
sym2,exch,1,server_a,port_a,info1,info2,info3
sym3,exch,0,info1,info2,info3
sym4,exch,2,server_a,port_a,server_d,port_c,info1,info2,info3
 

Словарь фрейма данных pandas, который мне понадобится, это:

 d = {"a": ["sym1", "sym2", "sym3", "sym4"], "b": ["blah", "blah", "blah", "blah"], "num_servers": [3, 1, 0, 2], "loc_0": ["server_a,port_a", "server_a,port_a", None, "server_a,port_a"], "loc_1": ["server_a,port_b", None, None, "server_d,port_c"], "loc_2": ["server_f,port_f", None, None, None], "info_1": ["info_1", "info_1", "info_1", "info_1"], "info_2": ["info_2", "info_2", "info_2", "info_2"], "info_3": ["info_3", "info_3", "info_3", "info_3"]}
 

Когда это находится в конце файла, легко выполнить цикл от первого столбца до конца, потому что в каждом столбце без сервера уже есть Nones, но я не знаю, как справиться с этим в середине. К сожалению, перезапись файла конфигурации невозможна.

Комментарии:

1. Что вам нужно в качестве выходных данных? Фрейм данных или словарь? Не могли бы вы пояснить. Кроме того, я бы попросил вас восстановить как вопрос, так и заголовок, поскольку они не очень понятны.

2. Мне требуется фрейм данных, но словарь был простым способом отображения выходных данных. Конечно, можно попытаться перефразировать

Ответ №1:

Я бы использовал модуль csv для анализа файла, потому что он может легко обрабатывать переменное количество полей. Код может быть:

 with open('file.csv') as fd:
    rd = csv.reader(fd)
    data = []                       # will build a list of records as dicts
    mx = 0
    for row in rd:
        num_servers = int(row[2])
        if num_servers > mx:        # keep the max number of servers
            mx = num_servers
        # build one record
        d = {'a': row[0], 'b': row[1], 'num_servers': num_servers,
             'info1': row[-3], 'info2': row[-2], 'info3': row[-3]}
        for i in range(num_servers):
            d['loc_'   str(i)] = '{},{}'.format(row[3   i * 2], row[4   i * 2])
        data.append(d)              # add the record to the list

cols = ['a', 'b', 'num_servers']    # build the list of columns
cols.extend('loc_'   str(i) for i in range(mx))
cols.extend(('info1', 'info2', 'info3'))
    
df = pd.DataFrame(data, columns=cols) # done...
 

В примере файла это дает:

       a     b  num_servers            loc_0            loc_1            loc_2  info1  info2  info3
0  sym1  exch            3  server_a,port_a  server_a,port_b  server_f,port_f  info1  info2  info1
1  sym2  exch            1  server_a,port_a              NaN              NaN  info1  info2  info1
2  sym3  exch            0              NaN              NaN              NaN  info1  info2  info1
3  sym4  exch            2  server_a,port_a  server_d,port_c              NaN  info1  info2  info1
 

Комментарии:

1. Это работает замечательно, опечатка в последнем «info3» должна быть -1, но в остальном работает блестяще