У меня есть pandas
DataFrame со следующими столбцами:
id | value | somedate
------------------------------
1 | [10, 13, 14] | 2024-06-01
2 | [5, 6, 7] | 2024-07-01
3 | [1, 2, 3] | 2024-06-01
Я выполняю следующее преобразование, чтобы проанализировать столбец value
и разбить DataFrame:
import ast
import pandas as pd
data = pd.DataFrame({"id": [1, 2, 3], "value": ["[10, 13, 14]", "[5, 6, 7]", "[1, 2, 3]"], "somedate": ["2024-06-01", "2024-07-01", "2024-06-01"]})
data["parsed_value"] = data["value"].apply(lambda x: ast.literal_eval(x))
data = data.explode(column = "parsed_value")
Это хорошо работает на небольших DataFrames, но становится невероятно медленным на очень больших DataFrames (от десятков до сотен миллионов строк).
Очевидно, что есть такие варианты, как параллельная обработка, переключение на другие пакеты, такие как dask
или polars
, но я просто хотел сначала убедиться, что я не упускаю какое-то очевидное решение в текущем стеке технологий.
Если вы предполагаете, что списки действительны и всегда представляют собой списки целых чисел, вы можете использовать регулярное выражение с str.extractall , а затем join:
out = data.join(data['value'].str.extractall(r'(\d+)')[0]
.astype(int)
.droplevel('match').rename('parsed_value'))
Выход:
id value somedate parsed_value
0 1 [10, 13, 14] 2024-06-01 10
0 1 [10, 13, 14] 2024-06-01 13
0 1 [10, 13, 14] 2024-06-01 14
1 2 [5, 6, 7] 2024-07-01 5
1 2 [5, 6, 7] 2024-07-01 6
1 2 [5, 6, 7] 2024-07-01 7
2 3 [1, 2, 3] 2024-06-01 1
2 3 [1, 2, 3] 2024-06-01 2
2 3 [1, 2, 3] 2024-06-01 3
Это почти в 2 раза быстрее для DataFrames из 1000+ строк:
Другое возможное решение — использование json.loads, который преобразует списки строк в списки:
import json
data.assign(parsed_value = data.value.map(json.loads)).explode('parsed_value')
Выход:
id value somedate parsed_value
0 1 [10, 13, 14] 2024-06-01 10
0 1 [10, 13, 14] 2024-06-01 13
0 1 [10, 13, 14] 2024-06-01 14
1 2 [5, 6, 7] 2024-07-01 5
1 2 [5, 6, 7] 2024-07-01 6
1 2 [5, 6, 7] 2024-07-01 7
2 3 [1, 2, 3] 2024-06-01 1
2 3 [1, 2, 3] 2024-06-01 2
2 3 [1, 2, 3] 2024-06-01 3
Спасибо! На самом деле это выполняется примерно за 4 секунды в моем наборе данных размером ~ 10 мм строк, и это идеально!
Добро пожаловать, @abudis!
Я попробовал это решение, которое выполняется примерно за 20 секунд в моем наборе данных длиной около 10 мм. Однако я заметил, что при разнесении получается неправильное количество строк. Я думаю, что предположение о том, что списки содержат только целые числа, не соответствует действительности, поскольку некоторые значения, вероятно, являются числами с плавающей запятой. В любом случае спасибо за этот ответ!