#python #pandas #list
#python #pandas #Список
Вопрос:
У меня есть функция, которая создает DataFrame
из списка списков:
def logs_reader():
path = Path("C:\Users\" getpass.getuser() "\DCBviz\logs\")
cols1 = ['Station ID', 'Reciever type', 'Satellite system', 'Date installed', 'Date removed']
cols2 = ['Station ID', 'Antenna type', 'Cable length', 'Date installed', 'Date removed']
file_list = [f for f in path.glob('**/*.log') if f.is_file()]
receivers_data = []
antennas_data = []
for file in file_list:
with open(file, encoding='utf8') as f:
contents = f.read()
station_id = re.findall("Four Character IDs*:s*(.*?)s*$", contents, re.MULTILINE)
receiver_types = re.findall("Receiver Types*:s*(.*?)s*$", contents, re.MULTILINE)
satellite_sys = re.findall("Satellite Systems*:s*(.*?)s*$", contents, re.MULTILINE)
date_installed = re.findall("Date Installeds*:s*(.*?)T.*$", contents, re.MULTILINE)
date_removed = re.findall("Date Removeds*:s*(.*?)T.*$", contents, re.MULTILINE)
antenna_types = re.findall("Antenna Types*:s*(.*?)s.*$", contents, re.MULTILINE)
cable_lengths = re.findall("Antenna Cable Lengths*:s*([0-9] .*[0-9]*)s.*$", contents, re.MULTILINE)
antenna_date_installed = re.findall("Date Installeds*:s*(.*?)T.*$", contents, re.MULTILINE)
antenna_date_removed = re.findall("Date Removeds*:s*(.*?)T.*$", contents, re.MULTILINE)
receivers_data.append([station_id, receiver_types, satellite_sys, date_installed, date_removed])
antennas_data.append([station_id, antenna_types, cable_lengths, antenna_date_installed, antenna_date_removed])
d = []
for l in receivers_data:
d.append({'Station ID': l[0]*len(l[1]),
'Reciever type': l[1],
'Satellite system': l[2],
'Date installed': l[3][0:len(l[1])],
'Date removed': l[4][0:len(l[1])]})
df = pd.DataFrame(d)
return df
df = logs_reader()
и в качестве возврата у меня есть фрейм данных, который выглядит так:
и я хочу разделить списки из столбцов 2-6 и создать отдельные записи из чистых записей с Station ID
в качестве многорядного индекса. Как я могу это сделать?
Желаемый результат:
Комментарии:
1. Было бы очень полезно, если бы вы создали простой фрейм данных, показывающий вашу проблему и ожидаемый результат от этих простых данных.
2. Вы ищете что-то вроде df.explode , но будьте осторожны, при последовательном отображении нескольких столбцов вы получите
n*m*p*q*r
строки3. Все ли списки имеют одинаковую длину? Возможно, вам было бы лучше создать отдельные dfs в вашей функции обнаружения, собрать их в dict с
'Station ID'
в качестве ключей и объединить все dfs сdf = pd.concat(dict.values(), keys=dict.keys())
4. Нет, они имеют разную длину
5. @RichieV итак, как мне нужно изменить эту функцию для создания отдельных dfs, как вы сказали?
Ответ №1:
Итак, у вас есть ваши данные с регулярным отображением в списках
receiver_types
satellite_sys
date_installed
date_removed
antenna_types
cable_lengths
antenna_date_installed
antenna_date_removed
Теперь я предполагаю, что каждый файл соответствует ОДНОМУ station_id
, но строка station_id = re.findall(...
все равно вернет список.
Тогда у вас будет station_id
, который представляет собой список длиной 1 и множество других списков. Если все списки получателей имеют одинаковую длину, вы можете создать df и собрать его в receivers_data
с помощью приведенного ниже кода (пожалуйста, скопируйте его снова, поскольку я убрал скобки вокруг station_id
).). А затем сделайте то же самое для antennae_data
.
Обратите внимание, что ваш текущий код отбрасывается df
на каждой итерации и возвращает данные только из последнего прочитанного файла.
Как я упоминал в комментариях, если все списки в одной строке имеют одинаковую длину, то лучшим вариантом является создание df из каждого файла и объединение их после цикла
Вы можете заменить строку
receivers_data.append([station_id, receiver_types, satellite_sys, date_installed, date_removed])
с
receivers_data.append(
pd.DataFrame(
[station_id * len(receiver_types), receiver_types, satellite_sys, date_installed, date_removed],
columns=list_of_column_names
)
)
# or instead of a list use a dict with file_name as keys
После того, как вы закончите чтение всех файлов, вы можете объединить оба списка с
df_receivers = pd.concat(receivers_data)
df_antennae = pd.concat(antennae_data)
Комментарии:
1. Я думаю, что есть небольшое недопонимание. Да, они имеют одинаковую длину, но после завершения второго
for
цикла. И я получаю df, который находится на экране.