У меня есть следующий фрейм данных, отображающий связь «один ко многим» между «курсами» и «уроками»:
course_id course_name lesson_id lesson_title
0 0 Learn C# 1 foo
1 0 Learn C# 2 bar
2 0 Learn C# 3 baz
3 1 Origami together 1 the crane
4 1 Origami together 2 crease patterns
5 2 WIP course 1 the first
Как мне отформатировать его так, чтобы:
каждая строка урока находится в пределах соответствующей строки курса
Столбцы lesson_id
и lesson_title
находятся под диапазоном общего столбца lessons
.
как показано ниже:
lessons
course_id course_name id title
0 0 Learn C# 1 foo
1 2 bar
2 3 baz
3 1 Origami together 1 the crane
4 2 crease patterns
5 2 WIP course 1 the first
и создаем результат, подобный этому, при экспорте в Excel:
Изучая подобные вопросы, я обнаружил, что принятые ответы включают использование мультииндекса, но в этом случае первый уровень индекса должен охватывать все столбцы, связанные с курсом.
Кроме того, стартовая таблица на самом деле генерируется динамически из соответствующих классов данных Course
и Lesson
, поэтому я боюсь, что этот подход не будет хорошо масштабироваться, если я добавлю атрибуты в класс Course
.
В идеале я бы проиндексировал course_id
и lesson_id
, а затем указал, какие столбцы индексируются первым или вторым, таким образом избегая дублирования атрибутов курса для каждого урока;
Есть ли способ добиться этого?
Если нужен MultiIndex в индексе и столбцах, можно использовать:
out = df.set_index(['course_id','course_name'])
out.columns = out.columns.str.split('_', expand=True)
Если вам нужны диапазоны строк для обоих уровней, вот трюк — вспомогательный столбец с пустыми строками:
out = df.assign(**{'':''}).set_index(['course_id','course_name', ''])
out.columns = out.columns.str.split('_', expand=True)
print (out)
lesson
id title
course_id course_name
0 Learn C 1 foo
2 bar
3 baz
1 Origami together 1 the crane
2 crease patterns
2 WIP course 1 the first
Если необходимо удалить третий столбец в Excel:
file = 'out.xlsx'
out.to_excel(file)
import xlwings as xw
wb = xw.Book(file)
wb.sheets['Sheet1'].range('C:C').delete()
wb.save(file)
@Afelium - Можешь проверить сейчас?
да, это исправило вывод при печати на консоли, хотя пустой столбец все еще виден при экспорте в Excel. Спасибо, что научили меня этому хаку, хотя, честно говоря, я надеялся на реальную поддержку панд, а не на обходные пути.
@Afelium — Не так просто, панды могут записывать данные только с помощью col/rowspan. Для удаления столбца C
используется xlwings
в отредактированном ответе.
Я применил ваш совет, и, несмотря на его включение в индекс,
course_name
по-прежнему повторяется для каждой строки. С другой стороны, колонкаlesson
получилась отличной.