- Вопрос или проблема
- Ответ или решение
- Переход от скрипта Python для трансформации данных к BigQuery
- 1. Проблема с данными
- 2. Переход к BigQuery
- Шаг 1: Загрузка данных
- Шаг 2: Генерация уникальных идентификаторов
- Шаг 3: Разделение на публичные и приватные таблицы
- 3. Регулярное обновление данных
- 4. Устранение проблем с дублированием
- Заключение
Вопрос или проблема
У меня есть набор данных, распределенный по нескольким постоянно растущим excel-файлам, каждый из которых выглядит так:
order_ID | order_date | |
---|---|---|
[email protected] | 1234 | 23-Mar-2021 |
[email protected] | 1235 | 23-Mar-2021 |
[email protected] | 1236 | 23-Mar-2021 |
[email protected] | 1237 | 24-Mar-2021 |
[email protected] | 1238 | 28-Mar-2021 |
Конечная цель состоит в том, чтобы получить два различных набора данных:
Первый набор – Заказы: (Публичный. Для анализа, торговые emails с user_ID для анонимности и пометка возвращающихся для дальнейшего анализа)
user_ID | order_ID | order_date | is_returning? |
---|---|---|---|
1 | 1234 | 23-Mar-2021 | 0 |
2 | 1235 | 23-Mar-2021 | 0 |
2 | 1236 | 23-Mar-2021 | 1 |
1 | 1237 | 24-Mar-2021 | 1 |
3 | 1238 | 28-Mar-2021 | 0 |
Второй набор – Пользователи (Частный для сохранения информации о пользователях. Имеются и другие столбцы, помимо email, но идея та же)
user_ID | |
---|---|
1 | [email protected] |
2 | [email protected] |
2 | [email protected] |
1 | [email protected] |
3 | [email protected] |
В pandas у меня есть следующая процедура:
-
Чтение всех файлов:
input_directory = 'Data/' files = os.listdir(input_directory) files
-
Объединение их:
all_data = pd.DataFrame() for df in data_dict.values(): all_data=pd.concat([all_data,df]).drop_duplicates().reset_index(drop=True) all_data = all_data.drop_duplicates()
-
Присвоение user ID:
all_data['user_id'] = all_data['email'].factorize()[0]
-
Присвоение флага возвратного пользователя:
all_data['is_returning'] = all_data.user_id.duplicated().astype(int)
-
Отправка обоих в BQ:
columns = #список приватных столбцов all_data.drop(columns, axis = columns).to_gbq(#параметры, table = `public_dataset.orders`) all_data[columns].to_gbq(#параметры, table = `private_dataset.users_db`)
Поскольку файлы постоянно приходят, мне нужно снова и снова переназначать user_IDs. (Потому что поиск соответствующего email для каждой строки в базе данных клиентов гораздо дороже, чем просто переназначение ID. Все анализы анонимны и основаны на общих числах, поэтому это не причинит вреда. Также поддержание локальной базы данных также не желательно, так как данные поступают в формате excel) Я могу создать скрипт для отправки данных только один раз, когда файл поступит, но не могу из-за
- Невозможности эмулировать
pd.factorize()
- И
duplicated()
в BigQuery - Невозможности заранее узнать, какие строки уже существуют, поскольку файлы могут содержать дублирующие записи,
Мне снова и снова приходится делать это. Так как я могу эффективно и экономично перейти на всю эту цепочку в BQ? Любая помощь в улучшении ситуации будет очень оценена
Возможное решение:
Присвоить каждому email/user UUID вместо ID с автоинкрементом (сначала убедившись, что email уже не существует, иначе использовать существующий UUID).
UUID могут быть созданы где угодно – не обязательно в БД – и почти гарантировано будут уникальны во времени и пространстве.
Например, количество случайных UUID версии 4, которые необходимо сгенерировать, чтобы вероятность хотя бы одного столкновения составила 50%, составляет 2.71 квинтиллиона, вычисленное следующим образом:
$${\displaystyle n\approx {\frac {1}{2}}+{\sqrt {{\frac{1}{4}}+2\times \ln(2)\times 2^{122}}}\approx 2.71\times 10^{18}.}$$
Это число эквивалентно генерации 1 миллиарда UUID в секунду примерно на 85 лет. Файл, содержащий такое количество UUID, при 16 байтах на UUID, составит около 45 эксабайт.
Примечание: Email пользователя также может быть использован в качестве уникального ID и делает все проще.
Ответ или решение
Переход от скрипта Python для трансформации данных к BigQuery
В современных условиях быстрого тарификации и обработки данных, переход от традиционного метода работы с файлами Excel и Python к облачным технологиям, таким как Google BigQuery, становится необходимостью для роста и масштабирования бизнеса. Рассмотрим подробно, как эффективно выполнить этот переход, оптимизировав процессы обработки данных.
1. Проблема с данными
Ваша задача заключается в обработке набора данных, который распределён по множеству файлов Excel. Каждый файл содержит информацию о заказах с полями, такими как email
, order_ID
и order_date
. Вам необходимо создать две отдельные таблицы:
- Orders – публичная, предназначенная для анализа, где
email
заменяется на анонимныеuser_ID
. - Users – приватная таблица, в которой хранятся контакты пользователей, включая их
email
.
Ваши текущие операции с данными выполняются с помощью библиотеки Pandas, но есть несколько ограничений, таких как необходимость повторной идентификации пользователей, чтобы избежать усложнения анализа.
2. Переход к BigQuery
Шаг 1: Загрузка данных
Для начала вам нужно собрать все данные из файлов Excel и загрузить их в BigQuery. В BigQuery можно создавать временные таблицы, чтобы сначала протестировать загружаемые данные. Вы можете использовать pandas-gbq
для загрузки данных:
import pandas as pd
# Чтение файлов и их объединение
input_directory = 'Data/'
all_data = pd.concat([pd.read_excel(f"{input_directory}/{file}") for file in os.listdir(input_directory)]).drop_duplicates().reset_index(drop=True)
# Загрузка данных в временную таблицу
all_data.to_gbq('temp_dataset.temp_orders', if_exists='replace')
Шаг 2: Генерация уникальных идентификаторов
Для генерации уникальных идентификаторов в BigQuery можно использовать функцию GENERATE_UUID()
. Это поможет избежать использования factorize()
и проблем с дублированием данных:
CREATE TABLE dataset.orders AS
SELECT
GENERATE_UUID() AS user_ID,
order_ID,
order_date,
COUNT(*) OVER (PARTITION BY email) > 1 AS is_returning
FROM temp_dataset.temp_orders
GROUP BY email, order_ID, order_date
Здесь мы создаём уникальный user_ID
для каждой строки и определяем, является ли пользователь возвращающимся, используя оконные функции.
Шаг 3: Разделение на публичные и приватные таблицы
После того, как вы сформировали публичную таблицу с анонимизированными данными, следующим шагом будет создание приватной таблицы пользователей:
CREATE TABLE dataset.users AS
SELECT
DISTINCT user_ID,
email
FROM temp_dataset.temp_orders
Эта таблица будет хранить уникальные адреса электронной почты пользователей.
3. Регулярное обновление данных
С учетом того, что данные поступают непрерывно, вы можете настроить регулярное обновление данных с помощью скриптов на Python, которые будут отслеживать новые поступления и загружать их в Базу Данных:
-
Автоматизация загрузки: Используйте Google Cloud Functions или другие средства планирования, такие как Apache Airflow, для автоматизации процесса загрузки данных.
-
Обработка новых файлов: Создайте логику для обработки только новых файлов. Таким образом, вы избежите загрузки данных, которые уже находятся в BigQuery.
4. Устранение проблем с дублированием
Поскольку ваш процесс будет уникален для каждого нового ввода данных, учитывайте, чтобы новые записи корректно проверялись на наличие дублирующихся:
- Обновление идентификации пользователей: Продумайте механизм, который будет проверять существующие адреса электронной почты в приватной таблице и будет генерировать новый
user_ID
, если такого адреса не существует.
Заключение
Переход на BigQuery не только оптимизирует процесс обработки данных, но также предлагает возможность масштабирования и повышения безопасности данных. Этот подход не только решит ваши текущие проблемы, такие как дублирование идентификаторов и вероятность ошибок в присутствии новых файлов, но и предоставит мощный инструмент для анализа данных. Не забудьте использовать возможности облачного хранилища для дополнительной безопасности и доступности данных.
Если вы будете следовать вышеуказанным рекомендациям, переход к BigQuery станет не только возможным, но и эффективным решением для вашего бизнеса, способствуя более глубокому анализу и адаптации к меняющимся условиям рынка.