Есть ли способ использовать jq для разделения файла JSON по его общим ключам? - PullRequest
0 голосов
/ 31 января 2019

У меня есть набор данных о ценах для большого количества акций (около 1,1 миллиона строк).

У меня проблемы с анализом всех этих данных в памяти, поэтому я хотел бы разделить их на акцииСимвол в отдельные файлы и импортировать данные только по мере необходимости.

С:

stockprices.json

Кому:

AAPL.json
ACN.json
...

и т. д.

В настоящее время stockprices.json имеет такую ​​структуру:

[{
    "date": "2016-03-22 00:00:00",
    "symbol": "ACN",
    "open": "121.029999",
    "close": "121.470001",
    "low": "120.720001",
    "high": "122.910004",
    "volume": "711400.0"
},
{
    "date": "2016-03-23 00:00:00",
    "symbol": "AAPL",
    "open": "121.470001",
    "close": "119.379997",
    "low": "119.099998",
    "high": "121.470001",
    "volume": "444200.0"
},
{
    "date": "2016-03-24 00:00:00",
    "symbol": "AAPL",
    "open": "118.889999",
    "close": "119.410004",
    "low": "117.639999",
    "high": "119.440002",
    "volume": "534100.0"
},
...{}....]

Я считаю, что jq - правильный инструмент для работы, но у меня возникают проблемы с его пониманием.

Как бы я взял данные вышеи использовать jq, чтобы разделить его на поле символа?

Например, я хотел бы получить:

AAPL.json:

[{
    "date": "2016-03-23 00:00:00",
    "symbol": "AAPL",
    "open": "121.470001",
    "close": "119.379997",
    "low": "119.099998",
    "high": "121.470001",
    "volume": "444200.0"
},
{
    "date": "2016-03-24 00:00:00",
    "symbol": "AAPL",
    "open": "118.889999",
    "close": "119.410004",
    "low": "117.639999",
    "high": "119.440002",
    "volume": "534100.0"
}]

и ACN.JSON:

[{
    "date": "2016-03-22 00:00:00",
    "symbol": "ACN",
    "open": "121.029999",
    "close": "121.470001",
    "low": "120.720001",
    "high": "122.910004",
    "volume": "711400.0"
},
    {
    "date": "2016-03-22 00:00:00",
    "symbol": "ACN",
    "open": "121.029999",
    "close": "121.470001",
    "low": "120.720001",
    "high": "122.910004",
    "volume": "711400.0"
}
]

Ответы [ 3 ]

0 голосов
/ 31 января 2019

Вот однопроходное решение, предполагающее, что ваша оперативная память достаточно велика.Решение избегает использования group_by, поскольку это влечет за собой операцию сортировки, которая является ненужной и потенциально дорогостоящей с точки зрения времени и памяти.

Для создания выходных файлов awk используется здесь для эффективности, но не имеет значения для подхода.

split.jq

def aggregate_by(s; f; g):
  reduce s as $x  (null; .[$x|f] += [$x|g]);

aggregate_by(.[]; .symbol; .)
| keys_unsorted[] as $k
| $k, .[$k]

Вызов с использованием awk

jq -f split.jq stockprices.json | awk '
  substr($0,1,1) == "\"" {
    if (fn) {close(fn)};
    gsub(/^"|"$/,"",$0); fn=$0 ".json"; next;
  }
  {print >> fn}'
0 голосов
/ 31 января 2019

Вам понадобится цикл, но это можно сделать за один вызов:

jq -rc 'group_by(.symbol)[] | "\(.[0].symbol)\t\(.)"' stockprices.json |
while IFS=$'\t' read -r symbol content; do
    echo "${content}" > "${symbol}.json"
done
0 голосов
/ 31 января 2019

Вы можете использовать небольшой цикл оболочки:

#!/bin/bash
jq -r '.[].symbol' stockprices.json | while read -r symbol ; do
    jq --arg s "${symbol}" \
        'map(if .symbol == $s then . else empty end)' \
    stockprices.json > "${symbol}".json
done 
...