#python #json #pandas #google-bigquery
#python #json #pandas #google-bigquery
Вопрос:
У меня есть столбец в одной из таблиц BigQuery, который выглядит следующим образом.
{"name": "name1", "last_delivered": {"push_id": "push_id1", "time": "time1"}, "session_id": "session_id1", "source": "SDK", "properties": {"UserId": "u1"}}
Есть ли какой-либо способ получить подобный вывод в GBQ?? (в основном разбить весь столбец на разные столбцы)
name last_delivered.push_id last_delivered.time session_id source properties.UserId
name1 push_id1 time1 session_id1 SDK uid1
Допустим
a = {«name»: «name1», «last_delivered»: {«push_id»: «push_id1», «time»: «time1»}, «session_id»: «session_id1», «source»: «SDK», «properties»: {«userId»: «u1»}}
Я пытался получить желаемый результат в Pandas Python, используя json_normalize (a), но каждый раз, когда я пытаюсь, получаю следующую ошибку
У кого-нибудь есть идеи, как я могу получить желаемый результат. Я что-то упускаю??
Любая помощь была бы с благодарностью принята!!
Комментарии:
1. Я скопировал ваш код в Spyder 3.6, и он работает так, как вы хотите: из pandas.io.json импортируйте json_normalize a = {«name»: «name1», «last_delivered»: {«push_id»: «push_id1», «time»: «time1»}, «session_id»: «session_id1», «source»: «SDK», «properties»: {» Идентификатор пользователя»: «u1»}} b = json_normalize(a) b Out[5]: last_delivered.push_id last_delivered.time … session_id source 0 push_id1 time1 … session_id1 SDK
2.
json_normalize
у меня работает.3. у меня тоже отлично работает
Ответ №1:
Приведенный ниже пример для стандартного SQL BigQuery
#standardSQL
WITH `project.dataset.table` AS (
SELECT '{"name": "name1", "last_delivered": {"push_id": "push_id1", "time": "time1"}, "session_id": "session_id1", "source": "SDK", "properties": {"UserId": "u1"}}' col
)
SELECT
JSON_EXTRACT_SCALAR(col, '$.name') name,
STRUCT(
JSON_EXTRACT_SCALAR(col, '$.last_delivered.push_id') AS push_id,
JSON_EXTRACT_SCALAR(col, '$.last_delivered.time') AS time
) last_delivered,
JSON_EXTRACT_SCALAR(col, '$.session_id') session_id,
JSON_EXTRACT_SCALAR(col, '$.source') source,
STRUCT(
JSON_EXTRACT_SCALAR(col, '$.properties.UserId') AS UserId
) properties
FROM `project.dataset.table`
и выдает результат, соответствующий ожидаемому / запрошенному
Row name last_delivered.push_id last_delivered.time session_id source properties.UserId
1 name1 push_id1 time1 session_id1 SDK u1
Комментарии:
1. Я знал это решение, но я хочу, чтобы столбцы были динамическими. Допустим, для других строк больше свойств, а для некоторых из них меньше значений. Я не пошел на это, потому что, по-моему, это слишком вручную. Что ж, если ничего не работает, это единственное решение, на которое я должен пойти. В любом случае, спасибо 🙂
2. Я ответил на ваш текущий вопрос. если у вас есть новый вопрос — пожалуйста, опубликуйте его как новый вопрос, и мы посмотрим, сможем ли мы вам помочь. Тем временем, подумайте хотя бы о том, чтобы проголосовать за ответ.
3. Спасибо Михаилу. Есть мысли о том, возможно ли это в Google big query ??… динамическое сглаживание.
4. обычно такого рода действия выполняются с помощью клиента по вашему выбору, такого как python. если вы хотите, чтобы это было сделано исключительно в BQ — вам нужно будет выполнить это в два этапа — сначала сгенерировать текст sql, а затем выполнить его. Я думаю, что этот двухэтапный подход будет выполним — но из-за ограниченной поддержки json для bq — это будет слишком сложно — поэтому я думаю, что использование клиентского подхода — это правильный путь
Ответ №2:
Я предполагаю, почему это не работает, потому что ваши данные json на самом деле являются строкой:
from pandas.io.json import json_normalize
a = '''{"name": "name1", "last_delivered": {"push_id": "push_id1", "time": "time1"}, "session_id": "session_id1", "source": "SDK", "properties": {"UserId": "u1"}}'''
df = json_normalize(a)
Вывод:
AttributeError: 'str' object has no attribute 'values'
Против:
from pandas.io.json import json_normalize
a = {"name": "name1", "last_delivered": {"push_id": "push_id1", "time": "time1"}, "session_id": "session_id1", "source": "SDK", "properties": {"UserId": "u1"}}
df = json_normalize(a)
Вывод:
print(df.to_string())
last_delivered.push_id last_delivered.time name properties.UserId session_id source
0 push_id1 time1 name1 u1 session_id1 SDK
Если это так, вы можете использовать json.loads()
прямо перед normalize:
import json
from pandas.io.json import json_normalize
a = '''{"name": "name1", "last_delivered": {"push_id": "push_id1", "time": "time1"}, "session_id": "session_id1", "source": "SDK", "properties": {"UserId": "u1"}}'''
data = json.loads(a)
df = json_normalize(data)
Комментарии:
1. Это отлично работает, спасибо, приятель !!…. но здесь я уменьшил проблему. Допустим, у нас есть фрейм данных с одним столбцом, имеющим такие значения. json.loads() принимает только одно строковое значение. Я знаю, что могу сохранить ее в цикле for , но проблема в том, что фрейм данных содержит миллионы строк…. Я думаю, что это займет много времени, если мы пойдем этим путем. Любым другим способом ??… с моей стороны тоже пытались.
2. Только что протестировал с 10 тысячами строк, сохранив ее в цикле for … боже! это заняло более ~ 30 минут. Что ж, результат — это то, чего я ожидаю. На каждый день приходится более миллиона строк, и я хотел делать это ежедневно. С вычислительной мощностью машин BQ я твердо уверен, что эти машины могут работать намного быстрее, при условии, что это осуществимо.