Описание проблемы:
У меня есть внешний файл * .xls, который я преобразовал в файл * .csv, содержащий блок данных, такой как:
"Legend number one";;;;Number of items;6
X;-358.6806792;-358.6716338;;;
Y;0.8767189;0.8966855;Avg;;50.1206378
Z;-0.7694626;-0.7520983;Std;;-0.0010354
D;8.0153902;8;Err;;1.010385
;;;;;
Естьмного много блоков.
Каждый блок может содержать некоторые дополнительные строки данных;
"Legend number six";;;;Number of items;19
X;-358.6806792;-358.6716338;;;
Y;0.8767189;0.8966855;Avg;;50.1206378
Z;-0.7654644;-0.75283;Std;;-0.0010354
D;8.0153902;8;Err;;1.010385
A;0;1;Value;;0
B;1;0;;;
;;;;;
Структура такова, что новая пустая строка отделяет каждый блок, то есть ';;;;;;»линия в моих образцах.
Первая строка после этого начинается с уникального идентификатора блока.
Кажется, что каждая строка содержит 6 элементов, таких как key1;elem1;elem2;key2;elem3;elem4
, которые было бы неплохо представить в виде двух 3-элементоввектор key1;elem1;elem2
и key2;elem3;elem4
на двух отдельных строках.Пример для второго примера:
"Legend number six";;
;;Number of items;19
X;-358.6806792;-358.6716338;
;;
Y;0.8767189;0.8966855;
Avg;;50.1206378
Z;-0.7654644;-0.75283;
Std;;-0.0010354
D;8.0153902;8;
Err;;1.010385
A;0;1;
Value;;0
B;1;0;
;;
;;;;;
Некоторые пустые, но я не хочу их сейчас отбрасывать.Но я хотел бы закончить DataFrame, содержащий элементы по столбцам для каждого блока данных.
Самое чистое «предварительное решение», которое у меня есть:
С этим кодом Python я оказался вболее организованный «Список словарей»:
import os, sys, re, glob
import pandas as pd
csvFile = os.path.join(workingDir,'file.csv')
h = 0 # Number of lines to skip in head
s = 2 # number of values per key
s += 1
str1 = 'Number of items'
# Reading file in a global list and storing each line in a sublist:
A = [line.split(';') for line in open(csvFile).read().split('\n')]
# This code splits each 6-elements sublist in one new sublist
# containing two-elements; each element with 3 values:
B = [(';'.join(el[:s])+'\n'+';'.join(el[s:])).split('\n') for el in A]
# Init empty structures:
names = [] # to store block unique identifier (the name in the legend)
L = [] # future list of dictionnaries
for el in (B):
for idx,elj in enumerate(el):
vi = elj.split(';')[1:]
# Here we grep the name only when the 2nd element of
# the first line contains the string "Number of items",
# which is constant all over the file:
if len(vi)>1 and vi[0]==str1:
name = el[idx-1].split(';')[0]
names.append(name)
#print(name)
# We loop again over B to append in a new list one dictionary
# per vector of 3 elements because each vector of 3 elements
# is structured like ; key;elem1;elem2
for el in (B):
for elj in (el):
k = elj.split(';')[0]
v = elj.split(';')[1:]
# Little tweak because the key2;elem3;elem4 of the
# first line (the one containing the name) have the
# key in the second place like "elem3;key2;elem4" :
if len(v)>1 and v[0]==str1:
kp = v[0]
v = [v[1],k]
k = kp
if k!='':
dct = {k:v}
L.append(dct)
Мне не удалось извлечь имя в качестве глобального идентификатора и все значения блоков до сих пор как переменные.Я не могу играть с какой-то методикой, основанной на модуле, из-за переменного количества информации в каждом отдельном блоке данных, даже если все блоки содержат хотя бы несколько общих ключей.
Я также пробовал условие while
в пределах for
цикл по всему словарю, но теперь это беспорядок.
zip
может быть хорошим вариантом, но я не знаю, как правильно его использовать.
Target DataFrame:
То, что я хотел бы получить, в идеале должно выглядеть примерно как DataFrame, содержащий:
index 'Number of items' 'X' '' 'Y' 'Avg' 'Z' 'Std' ...
"Legend number one" 6 ...
"Legend number six" 19 ...
"Legend number 11" 6 ...
"Legend number 15" 18 ...
Имена столбцов - это ключи, а таблица содержит значения для каждого блока данных в отдельной строке..
Если есть нумерованный индекс и новый столбец с именем легенды;все в порядке.
Пример CSV для игры:
"Legend number one";;;;Number of items;6
X;8.6806792;8.6716338;;;
Y;0.1557;0.1556;Avg;;50.1206378
Z;-0.7859;-0.7860;Std;;-0.0010354
D;8.0153902;8;Err;;1.010385
;;;;;
"Legend number six";;;;Number of items;19
X;56.6806792;56.6716338;;;
Y;0.1324;0.1322;Avg;;50.1206378
Z;-0.7654644;-0.75283;Std;;-0.0010354
D;8.0153902;8;Err;;1.010385
A;0;1;Value;;0
B;1;0;;;
;;;;;
"Legend number 11";;;;Number of items;6
X;358.6806792;358.6716338;;;
Y;0.1324;0.1322;Avg;;50.1206378
Z;-0.7777;-0.7778;Std;;-0.0010354
D;8.0153902;8;Err;;1.010385
;;;;;
"Legend number 15";;;;Number of items;18
X;58.6806792;58.6716338;;;
Y;0.1324;0.1322;Avg;;50.1206378
Z;0.5555;0.5554;Std;;-0.0010354
D;8.0153902;8;Err;;1.010385
A;0;1;Value;;0
B;1;0;;;
C;0;0;k;1;0
;;;;;
Я использую Ubuntu и Python 3.6, но сценарий должен работать и на компьютере с Windows.