У меня есть входная таблица Excel, подобная этой:
key | value | other data
------------------------- ...
k1 | v1 | d1
| v2 |
| v3 |
k2 | v2 | d2
| v5 |
k3 | v1 | d3
Значения хранятся в пустой, за исключением столбца значений, строке непосредственно под строкой с совпадающим ключом, и может быть произвольное количество значений, привязанных к ключу, однако крайне маловероятно, что больше трех. Все ключи уникальны, «другие данные» могут отсутствовать или повторяться, существует около дюжины значений и тысячи строк данных.
Мне нужно преобразовать входную таблицу в следующий формат:
k1 | v1,v2,v3 | d1 | ...
k2 | v2,v5 | d2 | ...
k3 | v1 | d3 | ...
Я решил эту проблему с помощью openpyxl и тривиального итеративного алгоритма, и мне было интересно, есть ли более элегантный способ сделать это с помощью средств манипулирования Pandas DataFrame? Я искал руководства по манипулированию данными Pandas, но большая часть того, что я смог найти, использует groupby()
и agg()
, что, по-видимому, не мой случай, поскольку у меня нет столбца, по которому я мог бы агрегировать, и он может зависеть только от постоянно уникального ключа.
Головное решение, которое я использовал на данный момент:
import openpyxl
wb = openpyxl.load_workbook('in.xlsx')
ws = wb['Sheet1']
row_data = None
out_list = list()
i = 2
while i < ws.max_row + 1:
if ws[i][0].value is not None:
if row_data is not None:
out_list += [row_data]
row_data = list(ws[i])
else:
row_data[1].value = f'{row_data[1].value}' + f',{ws[i][1].value}'
i += 1
out_list += [list(ws[ws.max_row])] # append the last row to the output
wb_out = openpyxl.Workbook()
ws_out = wb_out.active
for row in out_list:
ws_out.append([cell.value for cell in row])
wb_out.save('out.xlsx')
Способ pandas сделать это с учетом excel выглядит следующим образом:
df= pd.read_excel(r'C:\path\excelfile.xlsx',sheet_name='Sheet_Name')
df=(df.groupby(df.key.ffill()).agg({'value':lambda x: ','.join(x),'other data':'first'})
.reset_index())
key value other data
0 k1 v1,v2,v3 d1
1 k2 v2,v5 d2
2 k3 v1 d3