(1) Небольшой пример
В Pandas это очень просто, поскольку мы можем создать DataFrame за раз, например
>>> pd.DataFrame({
"A": {0: 'a', 20: 'b', 40: 'c'},
"B": {10: 'd', 20: 'e', 30: 'f'},
"C": {20: 'g', 30: 'h'},
}).sort_index()
A B C
0 a NaN NaN
10 NaN d NaN
20 b e g
30 NaN f h
40 c NaN NaN
но я не могу найти простой способ добиться аналогичного результата с помощью Polars. Как описано в разделе «Исходники из Pandas», Polars не использует индекс, в отличие от Pandas, и каждая строка индексируется по ее целочисленной позиции в таблице; поэтому мне может потребоваться представить «индексированную» серию с помощью DataFrame с двумя столбцами:
A = pl.DataFrame({ "index": [0, 20, 40], "A": ['a', 'b', 'c'] })
B = pl.DataFrame({ "index": [10, 20, 30], "B": ['d', 'e', 'f'] })
C = pl.DataFrame({ "index": [20, 30], "C": ['g', 'h'] })
Я пытался объединить эти несколько DataFrames, объединив их в столбце индекса:
>>> A.join(B, on='index', how='full', coalesce=True).join(C, on='index', how='full', coalesce=True).sort(by='index')
shape: (5, 4)
┌───────┬──────┬──────┬──────┐
│ index ┆ A ┆ B ┆ C │
│ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ str ┆ str │
╞═══════╪══════╪══════╪══════╡
│ 0 ┆ a ┆ null ┆ null │
│ 10 ┆ null ┆ d ┆ null │
│ 20 ┆ b ┆ e ┆ g │
│ 30 ┆ null ┆ f ┆ h │
│ 40 ┆ c ┆ null ┆ null │
└───────┴──────┴──────┴──────┘
Это дает желаемый результат, но мне интересно:
- (i) есть ли более краткий способ сделать это для многих столбцов и
- (ii) как сделать эту операцию максимально эффективной.
Я также пробовал внешние соединения, поскольку это один из способов объединить фреймы данных с разным количеством столбцов и строк, как описано выше.
Другое альтернативы, которые я пробовал, включают диагональную конкатенацию, но она не дедуплицирует и не объединяет индекс:
>>> pl.concat([A, B, C], how='diagonal')
index A B C
0 0 a None None
1 20 b None None
2 40 c None None
3 10 None d None
4 20 None e None
5 30 None f None
6 20 None None g
7 30 None None h
(2) Эффективное построение большой таблицы
Подход, который я нашел выше, дает желаемые результаты, которые мне хотелось бы, но я чувствую, что должен быть лучший путь с точки зрения производительности. Рассмотрим случай с более большими таблицами; скажем, 300 000 строк и 20 столбцов:
N, C = 300000, 20
pls = []
pds = []
for i in range(C):
A = pl.DataFrame({
"index": np.linspace(i, N*3-i, num=N, dtype=np.int32),
f"A{i}": np.arange(N, dtype=np.float32),
})
pls.append(A)
B = A.to_pandas().set_index("index")
pds.append(B)
Способ объединения двух столбцов подряд работает несколько медленнее, чем я ожидал:
%%time
F = functools.reduce(lambda a, b: a.join(b, on='index', how='full', coalesce=True), pls)
F.sort(by='index')
CPU times: user 1.49 s, sys: 97.8 ms, total: 1.59 s
Wall time: 611 ms
или однопроходное создание в pd.DataFrame:
%%time
pd.DataFrame({
f"A{i}": pds[f'A{i}'] for i in range(C)
}).sort_index()
CPU times: user 230 ms, sys: 50.7 ms, total: 281 ms
Wall time: 281 ms
Подробнее здесь: https://stackoverflow.com/questions/744 ... -sparse-se