いつも忘れてrange
?とかやってる。ちがう。seq
とsapply
。
> sapply(seq(0,7), function(i) { 2 ^ i }) [1] 1 2 4 8 16 32 64 128
DRY
いつも忘れてrange
?とかやってる。ちがう。seq
とsapply
。
> sapply(seq(0,7), function(i) { 2 ^ i }) [1] 1 2 4 8 16 32 64 128
DRY
fun1 <- function(x) { (x + 2) * (x - 4) } fun2 <- function(x) { (x + 1) * (x - 6) } v <- seq(-4, 8) plot(v, fun1(v), type="l", col="red") lines(v, fun2(v), col="blue")
# Datetime文字列のパース > t1 <- strptime("May 11 08:42:20", format = "%b %d %H:%M:%S" 1. ) > t2 <- strptime("May 11 08:47:23", format = "%b %d %H:%M:%S") # 時間の差分 > t2 - t1 Time difference of 5.05 mins # 秒でくれ > as.numeric(t2 - t1, units = "secs") [1] 303 >
strptime
: R: Date-time Conversion Functions to and from Characteras.numeric
: date - R Find time difference in seconds for YYYY-MM-DD HH:MM:SS.MMM format - Stack Overflow— 全年齢リツイート先生 (@otiai10) 2018年5月16日
統計ソフト「R」超入門 実例で学ぶ初めてのデータ解析 (ブルーバックス)
DRY
GAE/Goが好きなのでだいたいGAEでやっちゃおうとするんですけど、せっかくなのでCloud Functions使ってみたいじゃないですか。
すげー雑に、かんたんなことはGCFでやりましょう、となる。知らんけど。ある1つのトリガーに対して連鎖的に外部APIをトリガーしたいとき、みたいなシンプルで軽い用途に向いている、的な雰囲気だと思う。
% mkdir -p ~/tmp/gcftest % cd ~/tmp/gcftest % gcloud components update % gcloud projects create otiai10-gcftest
# ファイルつくります % vi hello.js % cat hello.js exports.hello = (req, res) => { res.send(`Hello World!`); } # デプロイします % gcloud functions deploy hello --trigger-http --project otiai10-gcftest API [cloudfunctions.googleapis.com] not enabled on project [otiai10-gcftest]. Would you like to enable and retry? (y/N)? y # 中略 Deploying function (may take a while - up to 2 minutes)...failed. ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Function load error: File index.js or function.js that is expected to define function does not exist in the root directory. # は? # function.js にする % ls -la % mv hello.js function.js # 再度デプロイを試みる % gcloud functions deploy hello --trigger-http --project otiai10-gcftest Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 entryPoint: hello httpsTrigger: url: https://us-central1-otiai10-gcftest.cloudfunctions.net/hello # 中略 status: ACTIVE timeout: 60s updateTime: '2018-04-27T06:15:24Z' versionId: '2
regionがus-central1になってるのがアレですが、
% curl https://us-central1-otiai10-gcftest.cloudfunctions.net/hello Hello World!% %
やるじゃん... 2分でできた。
とりあえずprojectの指定めんどいので
% gcloud config set project otiai10-gcftest
% gcloud functions --help % gcloud functions call --help # callでcurl相当のことができる % gcloud functions call hello executionId: dnaermtmefak result: Hello World! % % gcloud functions list NAME STATUS TRIGGER REGION hello ACTIVE HTTP Trigger us-central1 % gcloud functions describe hello # 削除 % gcloud functions delete hello Resource [projects/otiai10-gcftest/locations/us-central1/functions/hello] will be deleted. Do you want to continue (Y/n)? y Waiting for operation to finish...done. Deleted [projects/otiai10-gcftest/locations/us-central1/functions/hello]. % gcloud functions call hello ERROR: (gcloud.functions.call) ResponseError: status=[404], code=[Not Found], message=[Function hello in region us-central1 in project otiai10-gcftest does not exist] % # deployのオプションいろいろある % gcloud functions deploy --help # これとか --entry-point=ENTRY_POINT By default when a Google Cloud Function is triggered, it executes a JavaScript function with the same name. Or, if it cannot find a function with the same name, it executes a function named function. You can use this flag to override the default behavior, by specifying the name of a JavaScript function that will be executed when the Google Cloud Function is triggered. # deployのargに渡すNAMEが、HTTPのendpointになって、 # デフォルトではその名前が、exportされてる関数名と紐づくっぽい。 # --entry-pointでは、エントリポイントとなる関数名を指定できるようだ。 % gcloud functions deploy testtest \ --region ap-northeast1 \ --entry-point hello \ --trigger-http ERROR: (gcloud.functions.deploy) ResponseError: status=[400], code=[Bad Request], message=[The request has errors Problems: region asia-northeast1 is not supported. # マジか
あ、Tokyoにまだ来てないのか...
% gcloud functions deploy testtest \ --entry-point hello \ --trigger-http % curl https://us-central1-otiai10-gcftest.cloudfunctions.net/testtest Hello World!
やるじゃん...!
外部APIを叩かせるにはそのAPIシークレットをもたせる必要があるよなー、と思い。環境変数かな?と思ったけどそうではないのかな。
めんどくさそう。jsonでいいや。
const secrets = require("./secrets.json"); exports.leton = (req, res) => { res.send(secrets); }
% gcloud functions deploy leton --trigger-http % curl https://us-central1-otiai10-gcftest.cloudfunctions.net/leton {"name":"Hiromu OCHIAI","age":17} %
秘密が漏れてしまった。ソースコード管理・共有時はsecrets.json
をignoreするなりすればよいのだろうけど、アーキテクチャ的にプロジェクトのrootディレクトリをGCSに上げてるっぽいし、なんかちょっと気になるなと思った。ので質問してみた。
既出だったらすみません。GCFに、なんらかのシークレットを渡したい(だいたいの場合たぶん外部APIのトークンとか)場合のベストプラクティスって紹介されてますか? 環境変数かなと思ってググったらRuntime-Config とかいうやつにぶちあたったんですが、betaっぽいし、今の所普通にデプロイ対象ディレクトリ配下に
secrets.json
みたいなの作ってdeployしてます。
Functionかー。多少悩ましいねー 最近、適当にSecret ManagerのDemoアプリみたいなのを作ってみたりしていた https://github.com/sinmetal/gcpsm IAP, App Engine, Cloud KMS, Cloud Datastoreを使っている App Engineの時は、インスタンス起動時に取りに行って、メモリに持っておけばいいやーと思っていたけど、Functionですごい細かく起動する場合にこういうことするとLatencyとコストが多少気になるかも?
意外と無い。
意外とふわふわしてるんですね。KMSとかoverkillなので当面
secrets.json
でいいや、という気持ちにおちつきました :wink: ありがとうございます :bow:
世界中にオープンでいくらでもリクエストできるのはおかしい。限られた者からの呼び出しだけ許すにはどうすればよいか。
「CloudStorageへの権限をチェックする」という機構を使って、CloudFunctionsにおける認証機構を実現している。だるい。 これもsecrets.json
的な感じでまずは実装してしまおうと思う。
DRYな備忘録として
Rやりはじめた。
(1/n) * Σx(k)
x([n/2])
(1/n) * Σ((x(k) - av(k))^2)
√ ((1/n) * Σ((x(k) - av(k))^2))
なるほど。
サンプルデータを以下のように定義する。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
167.857 | 172.364 | 173.964 | 125.874 | 124.698 | 170.048 | 134.241 | 126.285 |
> n <- c(167.857,172.364,173.964,125.874,124.698,170.048,134.241,126.285)
> mean(n) [1] 149.4164
> median(n) [1] 151.049 > # 151.049 なんて要素無いが? > s <- sort(n) > mean(c(s[4], s[5])) [1] 151.049 > # 要素数が偶数なので、中央の2値の算術平均ということでした
※ Rは1-origin(インデックスが1から始まる)を知らず体感10分ぐらいハマった
> var(n) [1] 546.4991
ほんまかいな。ってことで、Pythonで確認。
>>> n = [167.857,172.364,173.964,125.874,124.698,170.048,134.241,126.285] >>> ave = 149.4164 >>> reduce(lambda x, y: x + (ave - y)**2, [0] + n) / len(n) 478.18674823500004
んんー違うぞ。
データの不偏分散を求める関数 var() は不偏分散を求める関数であって,標本分散を求める関数ではないことに注意
なるほど。標本分散を求める式をRでつくってみる。
> # 平均値を各要素に持つ要素数を一致させたベクトルをつくる > rep(mean(n), length(n)) [1] 149.4164 149.4164 149.4164 149.4164 149.4164 149.4164 149.4164 149.4164 > # これと標本集団との差分を取る > n - rep(mean(n), length(n)) [1] 18.44063 22.94763 24.54763 -23.54237 -24.71837 20.63163 -15.17537 [8] -23.13137 > # この各要素を自乗する > (n - rep(mean(n), length(n))) ** 2 [1] 340.0567 526.5935 602.5859 554.2434 610.9981 425.6640 230.2920 535.0605 > # この自乗した各要素を合計する > sum((n - rep(mean(n), length(n))) ** 2) [1] 3825.494 > # 要素数で割る > sum((n - rep(mean(n), length(n))) ** 2) / length(n) [1] 478.1867
Pythonでシコった値と一致した。
> sd(n) [1] 23.37732
Pythonで確認
>>> import math >>> math.sqrt(478.18674823500004) 21.86748152474354 # Rのsdの値と一致しないのは、 # Rのsdは不偏分散varの√を取ったものであろう # と予想。 >>> reduce(lambda x, y: x + (ave - y)**2, [0] + n) / (len(n) - 1) 546.49914084 # これが不偏分散。 # この√を取ると、 >>> math.sqrt(reduce(lambda x, y: x + (ave - y)**2, [0] + n) / (len(n) - 1)) 23.377321079199813 # Rのsdの値と一致した。
DRYな備忘録として
% brew install r
% R R version 3.5.0 (2018-04-23) -- "Joy in Playing" Copyright (C) 2018 The R Foundation for Statistical Computing Platform: x86_64-apple-darwin16.7.0 (64-bit) R は、自由なソフトウェアであり、「完全に無保証」です。 一定の条件に従えば、自由にこれを再配布することができます。 配布条件の詳細に関しては、'license()' あるいは 'licence()' と入力してください。 R は多くの貢献者による共同プロジェクトです。 詳しくは 'contributors()' と入力してください。 また、R や R のパッケージを出版物で引用する際の形式については 'citation()' と入力してください。 'demo()' と入力すればデモをみることができます。 'help()' とすればオンラインヘルプが出ます。 'help.start()' で HTML ブラウザによるヘルプがみられます。 'q()' と入力すれば R を終了します。 > q() Save workspace image? [y/n/c]: n %
> x <- c(10.4, 5.6, 3.1, 6.4, 21.7) > x [1] 10.4 5.6 3.1 6.4 21.7 > y <- 1/x > y [1] 0.09615385 0.17857143 0.32258065 0.15625000 0.04608295 > x + y [1] 10.496154 5.778571 3.422581 6.556250 21.746083 > x * y [1] 1 1 1 1 1
x
をつくるx
の各要素の逆数を要素とする1行5列のベクトルy
をつくるわかる。
ひきつづき。
統計ソフト「R」超入門 実例で学ぶ初めてのデータ解析 (ブルーバックス)