Ваша логика c почти верна, однако я подошел к вашей проблеме немного по-другому:
1) Сортируйте столбец, убедитесь, что все значения сгруппированы.
2) Сбросьте индекс (используя reset_index () и, возможно, передайте arg drop = True).
3) Затем мы должны захватить строки, в которых значение является новым. Для этого создайте список и добавьте первую строку 1, потому что оттуда мы обязательно начнем.
4) Затем начните итерацию по строкам этого списка и проверьте некоторые условия:
4a Если у нас только одна строка со значением, метод merge_range выдаст ошибку, потому что он не может объединить одну ячейку. В этом случае нам нужно заменить merge_range методом write.
4b) С этим алгоритмом вы получите ошибку индекса при попытке записать последнее значение в списке (потому что он сравнивает его с значение в следующей позиции индекса, и поскольку оно является последним значением в списке, следующей позиции индекса не существует). Поэтому нам нужно особо упомянуть, что если мы получим ошибку индекса (что означает, что мы проверяем последнее значение), мы хотим слить или записать до последней строки кадра данных.
4 c) Наконец, я не принимал во внимание, если столбец содержит пустые или нулевые ячейки. В этом случае код необходимо скорректировать.
Наконец, код может показаться немного запутанным, вы должны иметь в виду, что 1-я строка для pandas проиндексирована 0 (заголовки разделены), тогда как для заголовков xlsxwriter 0 индексируется, а первая строка индексируется 1.
Вот рабочий пример для достижения именно того, что вы хотите сделать:
import pandas as pd
# Create a test df
df = pd.DataFrame({'Name': ['Tesla','Tesla','Toyota','Ford','Ford','Ford'],
'Type': ['Model X','Model Y','Corolla','Bronco','Fiesta','Mustang']})
# Create the list where we 'll capture the cells that appear for 1st time,
# add the 1st row and we start checking from 2nd row until end of df
startCells = [1]
for row in range(2,len(df)+1):
if (df.loc[row-1,'Name'] != df.loc[row-2,'Name']):
startCells.append(row)
writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')
df.to_excel(writer, sheet_name='Sheet1', index=False)
workbook = writer.book
worksheet = writer.sheets['Sheet1']
merge_format = workbook.add_format({'align': 'center', 'valign': 'vcenter', 'border': 2})
lastRow = len(df)
for row in startCells:
try:
endRow = startCells[startCells.index(row)+1]-1
if row == endRow:
worksheet.write(row, 0, df.loc[row-1,'Name'], merge_format)
else:
worksheet.merge_range(row, 0, endRow, 0, df.loc[row-1,'Name'], merge_format)
except IndexError:
if row == lastRow:
worksheet.write(row, 0, df.loc[row-1,'Name'], merge_format)
else:
worksheet.merge_range(row, 0, lastRow, 0, df.loc[row-1,'Name'], merge_format)
writer.save()
Вывод: