顯示具有 index 標籤的文章。 顯示所有文章
顯示具有 index 標籤的文章。 顯示所有文章

2019年11月25日 星期一

jq 指令筆記 - 使用 to_entries 保留 key/value 資料,再用 select / index / match 過濾資料

人生就是有那種怪怪的堅持,明明寫個 php 或 python 就立刻可以解掉的需求,偏偏愛用 jq 來處理 XD

故事是來自於有個 key-value pair 的 json 資料:

% echo '{"A":{"field":"v1"},"B":{"field":"v2"}}' | jq ''
{
  "A": {
    "field": "v1"
  },
  "B": {
    "field": "v2"
  }
}


想要透過 jq 過濾時,也能保留 key 資料,這時就用 to_entries 來達成:

% echo '{"A":{"field":"v1"},"B":{"field":"v2"}}' | jq 'to_entries[]'
[
  {
    "key": "A",
    "value": {
      "field": "v1"
    }
  },
  {
    "key": "B",
    "value": {
      "field": "v2"
    }
  }
]

% echo '{"A":{"field":"v1"},"B":{"field":"v2"}}' | jq 'to_entries[]'
{
  "key": "A",
  "value": {
    "field": "v1"
  }
}
{
  "key": "B",
  "value": {
    "field": "v2"
  }
}


接著要再過濾指定欄位帶有 關鍵字 時,就靠 select 跟 index 來達成:

% echo '{"A":{"field":"v1"},"B":{"field":"v2"}}' | jq 'to_entries[] | select( .value.field | index("v2") >= 0 )'
{
  "key": "B",
  "value": {
    "field": "v2"
  }
}


此例是輸出 value.field 數值帶有 v2 關鍵字。而 index 之外的還有 match 等支援 regular expression 的用法,只是要用 !match 時有點卡卡串不太起來,就乾脆用 index 來處理。

2019年9月20日 星期五

jq 指令筆記 - 整理 JSON 資料,使用 select / index 過濾關鍵字

用 jq 去整理 api/json 的資料的。整個需求是:

  • API 回傳的 JSON 資料中,是一個 array 形式,裡頭的元素是 key-value pair
  • 透過 jq 把符合我需要的 資料列出
  • 檢查在某些條件上,有哪些東西,最後回歸到 comm 的工具幫忙導出結果進行比較

筆記一下 jq 項目:

$ cat /tmp/api.json | jq '.["data"]'
[
  {
    "field": "hello"
  },
  {
    "field": "world"
  }
]
$ cat /tmp/api.json | jq '.["data"] | .[] '
{
  "field": "hello"
}
{
  "field": "world"
}
$ cat /tmp/api.json | jq '.["data"] | .[] | select (.field | index("e") > 0) '
{
  "field": "hello"
}
$ cat /tmp/api.json | jq '.["data"] | .[] | select (.field | index("e") > 0) | .field '
"hello"


如此,可以結果導入檔案,如果需要比較檔案內的差異,就可以用 comm 指令來做事

2017年9月19日 星期二

[Python] 機器學習筆記 - 使用 Pandas 處理 CSV 格式、過濾資料與自身 Index 更新問題

使用 Pandas 套件進行分析資料時,它提供的功能包括便利的資料過濾:

import seaborn as sns
import pandas as pd

dataset = sns.load_dataset("tips")
print(dataset)
print(dataset.shape)
print(dataset.columns)

print("list total_bill > 30:")
print(dataset[ dataset['total_bill'] > 30 ] )


然而,預設 Pandas 會記錄原先的 raw index ,這也有不錯的功用,但有時希望照新的架構顯示,需要再多用 reset_index():

print("list total_bill > 30 and tip < 4:")
print(dataset[ (dataset['total_bill'] > 30) & (dataset['tip'] < 4) ] )

print("rebuild index:")
dataset = dataset[ (dataset['total_bill'] > 30) & (dataset['tip'] < 4) ]
dataset = dataset.reset_index()
print(dataset)


連續動作:

$ python pandas_study.py
     total_bill   tip     sex smoker   day    time  size
0         16.99  1.01  Female     No   Sun  Dinner     2
1         10.34  1.66    Male     No   Sun  Dinner     3
2         21.01  3.50    Male     No   Sun  Dinner     3
3         23.68  3.31    Male     No   Sun  Dinner     2
4         24.59  3.61  Female     No   Sun  Dinner     4
5         25.29  4.71    Male     No   Sun  Dinner     4
6          8.77  2.00    Male     No   Sun  Dinner     2
7         26.88  3.12    Male     No   Sun  Dinner     4
8         15.04  1.96    Male     No   Sun  Dinner     2
9         14.78  3.23    Male     No   Sun  Dinner     2
10        10.27  1.71    Male     No   Sun  Dinner     2
11        35.26  5.00  Female     No   Sun  Dinner     4
12        15.42  1.57    Male     No   Sun  Dinner     2
13        18.43  3.00    Male     No   Sun  Dinner     4
14        14.83  3.02  Female     No   Sun  Dinner     2
15        21.58  3.92    Male     No   Sun  Dinner     2
16        10.33  1.67  Female     No   Sun  Dinner     3
17        16.29  3.71    Male     No   Sun  Dinner     3
18        16.97  3.50  Female     No   Sun  Dinner     3
19        20.65  3.35    Male     No   Sat  Dinner     3
20        17.92  4.08    Male     No   Sat  Dinner     2
21        20.29  2.75  Female     No   Sat  Dinner     2
22        15.77  2.23  Female     No   Sat  Dinner     2
23        39.42  7.58    Male     No   Sat  Dinner     4
24        19.82  3.18    Male     No   Sat  Dinner     2
25        17.81  2.34    Male     No   Sat  Dinner     4
26        13.37  2.00    Male     No   Sat  Dinner     2
27        12.69  2.00    Male     No   Sat  Dinner     2
28        21.70  4.30    Male     No   Sat  Dinner     2
29        19.65  3.00  Female     No   Sat  Dinner     2
..          ...   ...     ...    ...   ...     ...   ...
214       28.17  6.50  Female    Yes   Sat  Dinner     3
215       12.90  1.10  Female    Yes   Sat  Dinner     2
216       28.15  3.00    Male    Yes   Sat  Dinner     5
217       11.59  1.50    Male    Yes   Sat  Dinner     2
218        7.74  1.44    Male    Yes   Sat  Dinner     2
219       30.14  3.09  Female    Yes   Sat  Dinner     4
220       12.16  2.20    Male    Yes   Fri   Lunch     2
221       13.42  3.48  Female    Yes   Fri   Lunch     2
222        8.58  1.92    Male    Yes   Fri   Lunch     1
223       15.98  3.00  Female     No   Fri   Lunch     3
224       13.42  1.58    Male    Yes   Fri   Lunch     2
225       16.27  2.50  Female    Yes   Fri   Lunch     2
226       10.09  2.00  Female    Yes   Fri   Lunch     2
227       20.45  3.00    Male     No   Sat  Dinner     4
228       13.28  2.72    Male     No   Sat  Dinner     2
229       22.12  2.88  Female    Yes   Sat  Dinner     2
230       24.01  2.00    Male    Yes   Sat  Dinner     4
231       15.69  3.00    Male    Yes   Sat  Dinner     3
232       11.61  3.39    Male     No   Sat  Dinner     2
233       10.77  1.47    Male     No   Sat  Dinner     2
234       15.53  3.00    Male    Yes   Sat  Dinner     2
235       10.07  1.25    Male     No   Sat  Dinner     2
236       12.60  1.00    Male    Yes   Sat  Dinner     2
237       32.83  1.17    Male    Yes   Sat  Dinner     2
238       35.83  4.67  Female     No   Sat  Dinner     3
239       29.03  5.92    Male     No   Sat  Dinner     3
240       27.18  2.00  Female    Yes   Sat  Dinner     2
241       22.67  2.00    Male    Yes   Sat  Dinner     2
242       17.82  1.75    Male     No   Sat  Dinner     2
243       18.78  3.00  Female     No  Thur  Dinner     2

[244 rows x 7 columns]
(244, 7)
Index(['total_bill', 'tip', 'sex', 'smoker', 'day', 'time', 'size'], dtype='object')
list total_bill > 30:
     total_bill    tip     sex smoker   day    time  size
11        35.26   5.00  Female     No   Sun  Dinner     4
23        39.42   7.58    Male     No   Sat  Dinner     4
39        31.27   5.00    Male     No   Sat  Dinner     3
44        30.40   5.60    Male     No   Sun  Dinner     4
47        32.40   6.00    Male     No   Sun  Dinner     4
52        34.81   5.20  Female     No   Sun  Dinner     4
56        38.01   3.00    Male    Yes   Sat  Dinner     4
59        48.27   6.73    Male     No   Sat  Dinner     4
83        32.68   5.00    Male    Yes  Thur   Lunch     2
85        34.83   5.17  Female     No  Thur   Lunch     4
95        40.17   4.73    Male    Yes   Fri  Dinner     4
102       44.30   2.50  Female    Yes   Sat  Dinner     3
112       38.07   4.00    Male     No   Sun  Dinner     3
141       34.30   6.70    Male     No  Thur   Lunch     6
142       41.19   5.00    Male     No  Thur   Lunch     5
156       48.17   5.00    Male     No   Sun  Dinner     6
167       31.71   4.50    Male     No   Sun  Dinner     4
170       50.81  10.00    Male    Yes   Sat  Dinner     3
173       31.85   3.18    Male    Yes   Sun  Dinner     2
175       32.90   3.11    Male    Yes   Sun  Dinner     2
179       34.63   3.55    Male    Yes   Sun  Dinner     2
180       34.65   3.68    Male    Yes   Sun  Dinner     4
182       45.35   3.50    Male    Yes   Sun  Dinner     3
184       40.55   3.00    Male    Yes   Sun  Dinner     2
187       30.46   2.00    Male    Yes   Sun  Dinner     5
197       43.11   5.00  Female    Yes  Thur   Lunch     4
207       38.73   3.00    Male    Yes   Sat  Dinner     4
210       30.06   2.00    Male    Yes   Sat  Dinner     3
212       48.33   9.00    Male     No   Sat  Dinner     4
219       30.14   3.09  Female    Yes   Sat  Dinner     4
237       32.83   1.17    Male    Yes   Sat  Dinner     2
238       35.83   4.67  Female     No   Sat  Dinner     3
list total_bill > 30 and tip < 4:
print index:
index: 56
index: 102
index: 173
index: 175
index: 179
index: 180
index: 182
index: 184
index: 187
index: 207
index: 210
index: 219
index: 237
rebuild index:
    index  total_bill   tip     sex smoker  day    time  size
0      56       38.01  3.00    Male    Yes  Sat  Dinner     4
1     102       44.30  2.50  Female    Yes  Sat  Dinner     3
2     173       31.85  3.18    Male    Yes  Sun  Dinner     2
3     175       32.90  3.11    Male    Yes  Sun  Dinner     2
4     179       34.63  3.55    Male    Yes  Sun  Dinner     2
5     180       34.65  3.68    Male    Yes  Sun  Dinner     4
6     182       45.35  3.50    Male    Yes  Sun  Dinner     3
7     184       40.55  3.00    Male    Yes  Sun  Dinner     2
8     187       30.46  2.00    Male    Yes  Sun  Dinner     5
9     207       38.73  3.00    Male    Yes  Sat  Dinner     4
10    210       30.06  2.00    Male    Yes  Sat  Dinner     3
11    219       30.14  3.09  Female    Yes  Sat  Dinner     4
12    237       32.83  1.17    Male    Yes  Sat  Dinner     2
print index:
index: 0
index: 1
index: 2
index: 3
index: 4
index: 5
index: 6
index: 7
index: 8
index: 9
index: 10
index: 11
index: 12

2017年9月14日 星期四

[MySQL] 從 JSON 抽取資料建立虛擬欄位 @ MySQL 5.7

同事反映 query 很慢,除了改進 SQL 語法外,也小試身手,對 JSON 資料抽出來建立虛擬欄位跟索引,順便筆記一下。

CREATE TABLE `my_data` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `data` text,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


這邊 data column 是 text 型態,主因是這 DB server 從 5.6 升上來的 XD 且當初讓 data 有很多彈性,不一定是 json 格式。

但,要抽取成虛擬欄位時,建議要保持 data 是 json 格式,就先整理一下資料:

mysql> UPDATE my_data SET data = '{}' WHERE data IS NULL OR data = ''

假想 data 的數值為 {"keyword":"value"},因此抽出 keyword 虛擬欄位來用:

mysql> ALTER TABLE my_data ADD keyword VARCHAR(64) AS (JSON_UNQUOTE(data->>"$. keyword"));
mysql> ALTER TABLE my_data ADD INDEX (keyword);


如此一來,可以改對 keyword 欄位查詢了,可以再加快一點,而 table 狀態更新為:

CREATE TABLE `my_data ` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `data` text,
  `keyword` varchar(64) GENERATED ALWAYS AS (json_unquote(json_unquote(json_extract(`data`,'$. keyword')))) VIRTUAL,
  PRIMARY KEY (`id`),
  KEY `keyword ` (`keyword `),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2015年10月29日 星期四

[Linux] PostgreSQL 9.4 簡易筆記 - 建立資料庫、使用者、索引 @ Ubuntu 14.04

安裝:

$ sudo apt-get install postgresql-9.4

列出已存在的資料庫:

$ sudo -u postgres psql -l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(3 rows)


建立資料庫:

$ sudo -u postgres createdb MyDB

刪除資料庫:

$ sudo -u postgres dropdb MyDB

建立使用者(-P: 建立密碼, -l: 有登入權限[預設], -L: 禁止登入, -s: 超級使用者, -d: 建立資料庫權限):

$ sudo -u postgres createuser -P -s -d -l root
$ sudo -u postgres createuser -s -d -l user1
$ sudo -u postgres createuser -s -l user2
$ sudo -u postgres createuser -l user3
$ sudo -u postgres createuser -d user4
$ sudo -u postgres createuser -s user5


列出使用者列表:

$ sudo -u postgres psql -c "SELECT * FROM pg_user";
 usename  | usesysid | usecreatedb | usesuper | usecatupd | userepl |  passwd  | valuntil | useconfig
----------+----------+-------------+----------+-----------+---------+----------+----------+-----------
 postgres |       10 | t           | t        | t         | t       | ******** |          |
 user1    |    ####1 | t           | t        | t         | f       | ******** |          |
 user2    |    ####2 | t           | t        | t         | f       | ******** |          |
 user3    |    ####3 | f           | f        | f         | f       | ******** |          |
 user4    |    ####4 | t           | f        | f         | f       | ******** |          |
 user5    |    ####5 | t           | t        | t         | f       | ******** |          |
 root     |    ####6 | t           | t        | t         | f       | ******** |          |
(7 rows)


刪除帳號:

$ sudo -u postgres dropuser user1
$ sudo -u postgres dropuser user2
$ sudo -u postgres dropuser user3
$ sudo -u postgres dropuser user4
$ sudo -u postgres dropuser user5


遠端登入資料庫(資料庫跟使用者必須先建立):

$ sudo -u postgres createdb helloworld
$ sudo -u postgres createuser -P -l user1
$ sudo -u postgres createuser -P -L user2

$ psql -h localhost -U user1
Password for user user1:
psql: FATAL:  database "user1" does not exist

$ psql -h localhost -U user1 -d helloworld
Password for user user1:
psql (9.4.4)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

helloworld=>\q

$ psql -h localhost -U user2 -d helloworld
Password for user user2:
psql: FATAL:  role "user2" is not permitted to log in


以下皆在 helloworld 資料庫行動:

$ psql -h localhost -U user1 -d helloworld
Password for user user1:
psql (9.4.4)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

helloworld=>


建立資料表:

helloworld=> CREATE TABLE haha ( field1 INT, field2 VARCHAR(64) );
CREATE TABLE
helloworld=> CREATE TABLE hehe ( field1 TEXT );


列出資料表:

helloworld=> \d
       List of relations
 Schema | Name | Type  | Owner
--------+------+-------+-------
 public | haha | table | user1
 public | hehe | table | user1
(2 rows)


查詢資料表定義:

helloworld=> \d haha
            Table "public.haha"
 Column |         Type          | Modifiers
--------+-----------------------+-----------
 field1 | integer               |
 field2 | character varying(64) |


刪除資料表:

helloworld=> DDROP TABLE haha;
DROP TABLE


建立索引:

helloworld=> CREATE INDEX index_test ON hehe ( field1 );
helloworld=> \d hehe
    Table "public.hehe"
 Column | Type | Modifiers
--------+------+-----------
 field1 | text |
Indexes:
    "index_test" btree (field1)


刪除索引:

helloworld=> DROP INDEX index_test;
DROP INDEX
helloworld=> \d hehe
    Table "public.hehe"
 Column | Type | Modifiers
--------+------+-----------
 field1 | text |


建立 Partial Indexes:

helloworld=> CREATE INDEX index_substring ON hehe ( substring(field1, 0, 32) );
CREATE INDEX
helloworld=> CREATE INDEX index_condition ON hehe ( field1 )
helloworld->  WHERE substring(field1, 0, 1) = 'a' ;
CREATE INDEX
helloworld=> \d hehe
    Table "public.hehe"
 Column | Type | Modifiers
--------+------+-----------
 field1 | text |
Indexes:
    "index_condition" btree (field1) WHERE "substring"(field1, 0, 1) = 'a'::text
    "index_substring" btree ("substring"(field1, 0, 32))


從 STDIN 輸入資料至 helloworld.hehe 中:

$ bash --version
GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

$ cat <<EOF | psql -h localhost -U user1 -W -d helloworld
> COPY hehe (field1) FROM stdin;
> 1
> 2
> 3
> 4
> 5
> 6
> EOF
Password for user user1:
COPY 6

$ psql -h localhost -U user1 -W -d helloworld -c 'SELECT * FROM hehe;'
Password for user user1:
 field1
--------
 1
 2
 3
 4
 5
 6
(6 rows)