Openpyxl - Добавить ключ, пары значений из двух разных строк Excel в словаре - PullRequest
0 голосов
/ 10 апреля 2020

Я пытаюсь здесь сохранить значения ячеек из указанной строки c как ключи, а значения ячеек из другой строки - как значения, все вместе в словаре.

Используя приведенный ниже код, я удалось сохранить первую строку (отмечена зеленым) в качестве ключей в словаре.

Но я борюсь с тем, чтобы сохранить вторую строку (отмеченную желтым цветом) как значения в словаре.

dictData = {}

#get row 2 
for row1 in ws1.iter_rows(min_row=2, max_row=2, min_col=3, max_col=ws1.max_column):
    for cell1 in row1:
        #get row 5
        for row2 in ws1.iter_rows(min_row=5, max_row=row_data, min_col=5, max_col=ws1.max_column):
            for cell2 in row2:
                    dictData[cell1.value] = cell2.value

Table

При выполнении вышеупомянутого кода он сохраняет для каждого значения в словаре только последние данные из строки ("20" -данные из Китая ).

{'Total': 20, 'USA': 20, 'Canada': 20, 'UK': 20, 'France': 20, 'Germany': 20, 'India': 20, 'Japan': 20, 'Singapore': 20, 'China': 20}

У кого-нибудь есть идеи / отзывы о том, как решить эту проблему? Наверняка я что-то упускаю в 'для l oop'.

Спасибо! :)

Ответы [ 3 ]

1 голос
/ 10 апреля 2020

Это не требует вложенного l oop. Для каждого внешнего значения (ключа dict) вам нужно только одно внутреннее значение (значение dict). Таким образом, внутренний l oop должен иметь размер 1, который вообще не равен l oop.

Однако вы, конечно, должны выровнять свои внутренние значения с внешними. В большинстве классических языков программирования это может быть достигнуто циклически по индексу, используемому для адресации обоих элементов, например

# Naive way
dictData = {}
for i in range(2, len(ws1[3])):
    dictData[ws1[3][i].value] = ws1[5][i].value

Это, однако, не очень pythoni c, так как Python позволяет выполнять циклическое выполнение непосредственно по ценности. Но зацикливание только на внешних значениях все еще требует индекса внутренних значений. Это можно найти, используя enumerate в l oop, чтобы получить и значение, и его индекс:

# Enumerate inner value (not very nice)
dictData = {}
for i, key in enumerate(ws1[3][2:], 2):
    dictData[key.value] = ws1[5][i].value 

Тем не менее, это не так много, как нам нужен индекс. Мы действительно хотим иметь возможность получить ключ dict и значение dict непосредственно из l oop. И, о чудо, Python имеет готовое для нас решение, а именно использование zip, которое позволяет нам выровнять две серии в одну for l oop:

# Using zip, nicer and more pythonic
dictData = {}
for key, value in zip(ws1[3][2:], ws1[5][2:]):
    dictData[key.value] = value.value 

Теперь мы добраться куда-то Это больше похоже на это, но мы можем go еще дальше, используя так называемое понимание dict, которое позволяет нам создавать и назначать dict за один go:

# dict comprehension
dictData = {key.value: value.value for key, value in zip(ws1[3][2:], ws1[5][2:])}

Любой из последних Во-вторых, я бы сказал, что все в порядке, хотя я предпочитаю понимать слова, потому что читать его довольно легко, но ваш пробег может отличаться.

Кроме того, в заключение, чтобы код чувствовался больше pythoni c, замените camelCased dictData на более PEP8-совместимую форму dict_data. Но это, конечно, правильно, если этот стиль используется для всех переменных в вашем проекте. Более важно быть последовательным.

1 голос
/ 11 апреля 2020

только что посмотрел на ваши общие данные; поскольку вас интересуют только две строки (строки 2 и 5), вы можете читать их по отдельности, архивировать данные и определять сжатые данные. соответствующие данные начинаются со столбца 3, поэтому я включил их также:

from openpyxl import load_workbook
filename = 'Project_yxz.xlsx'

wb = load_workbook(filename)
ws = wb.active

#read in the data
row2 = ws.iter_rows(min_row=2, max_row=2, min_col=3, values_only=True)
row5 = ws.iter_rows(min_row=5, max_row=5, min_col=3, values_only=True)

#zip and dict
res = dict(zip(*row2,*row5))

res

{'Total': 720,
 'USA': 72,
 'Canada': 34,
 'UK': 54,
 'France': 46,
 'Germany': 38,
 'India': 120,
 'Japan': 101,
 'Singapore': 47,
 'China': 20}

Дай мне знать, если это то, что ты имеешь в виду. дальнейшее чтение из документации openpyxl здесь

1 голос
/ 10 апреля 2020

Старайтесь не вкладывать итерации. Прочитайте строку 2 самостоятельно.

Затем повторите от 5 до чего-то.

Если вам нужен заголовок для чего-то, сохраните его в другом каталоге, например, с именем столбца в качестве ключа. Затем обратитесь к нему позже.

Вы создаете следующий словарь из первой строки:

headers = {1:'Total', 2:'USA'}

Позже, когда вы перебираете остальные строки и столбцы, вы получаете к нему доступ, чтобы получить имя. Вы знаете индекс столбца. Может быть, вам нужно исправить смещение или что-то в этом роде.

some_other_dictionary = {headers[column_index]: 'some_value'}

Другая возможность - использовать что-то вроде pandas .read_excel , которое должно выполнить тяжелую работу за вас.

...