@kyanny's blog

My thoughts, my life. Views/opinions are my own.

Twitter iOS アプリからログアウトした。極力フォローしないようにしてるので*1タイムラインは平穏だけど、ついつい検索からトレンドとかを見てしまい、毎日のように選挙がらみの極端な意見やニュースに対するヒステリックな反応ばかり目にして精神衛生に良くないと感じていた。いくつか懸念点があったがクリアできそうな目処がたったので、アプリからログアウトした*2

たまに書きたいことはあるので(それもなるべく書かないほうがいいが)、ずいぶん前に見つけて使ってなかった Outputter というアプリを使うことにした。あの FastEver の開発元である Rakko Inc. の作品。

Outputter for Twitter

Outputter for Twitter

  • Rakko Inc.
  • ソーシャルネットワーキング
  • 無料

メンションは Outputter でチェックできる。DM は読み書きできないが、Twitter の通知設定で DM 通知をメールで受け取れるのでそれで気づくことはできそう。知人の非公開アカウントをどう見るかが悩みどころだったが、Zapier から LINE Notify に流すことにした*3

Twitter にも書こうかと思ったが、メンションや DM には引き続き反応できるはずだし、投稿もできるので、わざわざ「あなたたちのツイートは見ませんのであしからず」的な意味になるアナウンスをする必要はない(ただ感じ悪いだけ)と思い、やめにした。ここにも書く必要はないのだけど、これは日記なので要不要とは無関係に書き残すべきことを書くのみ。

浮いた時間を他のどうしようもないモノで浪費しないように気をつけたい。たぶんたいして見るべきものもないのに Facebook アプリをだらだら見てしまいそうなので、そちらはいっそ削除したほうがよいかもしれない。

*1:いまはフォロー 100 アカウント以内を心がけてる

*2:アプリごと消さないのは、別のアカウントでログインしていて妻がたまに使うため

*3:おれが見るだけなら Reeder で購読できるのだが、その人はたまに飼い猫の写真をあげてくれて、妻が楽しみにしているので、妻にもあとで見せられる方法が必要

Ruby: CSV.filter のオプションに return_headers と write_headers の両方を指定するとヘッダが 2 行でる

TL;DR

headers: truereturn_headers: true を指定すること(write_headers は指定しないこと)。

ruby -v
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]
echo "a,b\n1,2" | ruby -r csv -e 'CSV.filter(headers: true, return_headers: true, write_headers: true){ |row| p [row.class, row]}'
[Array, ["a", "b"]]
a,b
[CSV::Row, #<CSV::Row "a":"a" "b":"b">]
a,b
[CSV::Row, #<CSV::Row "a":"1" "b":"2">]
1,2

write_headers を特別扱いしているが、これがかえって悪さをしている気がする。

ruby/csv.rb at 5921bfc7ce91aa8079dd8ac4faf873ec911ce320 · ruby/ruby · GitHub

CSV.filter のブロック内でヘッダ行を CSV::Row インスタンスとして処理したい場合は return_headers: true が必要なので、write_headers を指定しないのが正解。

echo "a,b\n1,2" | ruby -r csv -e 'CSV.filter(headers: true, return_headers: true){ |row| p [row.class, row]}'
[CSV::Row, #<CSV::Row "a":"a" "b":"b">]
a,b
[CSV::Row, #<CSV::Row "a":"1" "b":"2">]
1,2
echo "a,b\n1,2" | ruby -r csv -e 'CSV.filter(headers: true, return_headers: true){ |row| row.header_row? && row[0]=row[0].upcase }'
A,b
1,2

return_headers: true の代わりに write_headers: true でもヘッダ行はブロックに渡されるが、CSV::Row インスタンスではなく Array になるので適切なインスタンスメソッドが使えない。

echo "a,b\n1,2" | ruby -r csv -e 'CSV.filter(headers: true, write_headers: true){ |row| p [row.class, row]}'
[Array, ["a", "b"]]
a,b
[CSV::Row, #<CSV::Row "a":"1" "b":"2">]
1,2
echo "a,b\n1,2" | ruby -r csv -e 'CSV.filter(headers: true, write_headers: true){ |row| row.header_row? && row[0]=row[0].upcase }'
-e:1:in `block in <main>': undefined method `header_row?' for ["a", "b"]:Array (NoMethodError)

CSV.filter(headers: true, write_headers: true){ |row| row.header_row? && row[0]=row[0].upcase }
                                                         ^^^^^^^^^^^^
    from /Users/kyanny/.rbenv/versions/3.1.2/lib/ruby/3.1.0/csv.rb:1093:in `filter'
    from -e:1:in `<main>'

CSV.filter (Ruby 3.1 リファレンスマニュアル) のサンプルコードのように return_headers: truewrite_headers: true を両方指定すると、冒頭の実行例のようにヘッダ行が 2 行出力されるばかりか、最初のヘッダ行は Array のインスタンスなので適切なインスタンスメソッドが使えない。サンプルコードどおりに実装しても動作せず、ハマる。

echo "a,b\n1,2" | ruby -r csv -e 'CSV.filter(headers: true, return_headers: true, write_headers: true){ |row| row.header_row? && row[0]=row[0].upcase }'
-e:1:in `block in <main>': undefined method `header_row?' for ["a", "b"]:Array (NoMethodError)

CSV.filter(headers: true, return_headers: true, write_headers: true){ |row| row.header_row? && row[0]=row[0].upcase }
                                                                               ^^^^^^^^^^^^
    from /Users/kyanny/.rbenv/versions/3.1.2/lib/ruby/3.1.0/csv.rb:1093:in `filter'
    from -e:1:in `<main>'

CSV.filter (Ruby 3.1 リファレンスマニュアル) のサンプルコードは他にも間違っていて、CSV.filterHash インスタンスとして options を渡しているが、これだとキーワード引数ではなく第一引数と解釈され、第一引数は StringIO のインスタンスを期待しているので、実行時エラーになる。

echo "a,b\n1,2" | ruby -e 'require "csv"

options = { headers: true, return_headers: true, write_headers: true }

CSV.filter(options) do |row|
  if row.header_row?
    row << "header3"
    next
  end
  row << "row1_3"
end'
/Users/kyanny/.rbenv/versions/3.1.2/lib/ruby/3.1.0/csv/parser.rb:237:in `read_chunk': private method `gets' called for {:headers=>true, :return_headers=>true, :write_headers=>true}:Hash (NoMethodError)

          chunk = input.gets(@row_separator, @chunk_size)
                       ^^^^^
    from /Users/kyanny/.rbenv/versions/3.1.2/lib/ruby/3.1.0/csv/parser.rb:95:in `initialize'
    from /Users/kyanny/.rbenv/versions/3.1.2/lib/ruby/3.1.0/csv/parser.rb:795:in `new'
    from /Users/kyanny/.rbenv/versions/3.1.2/lib/ruby/3.1.0/csv/parser.rb:795:in `build_scanner'
    from /Users/kyanny/.rbenv/versions/3.1.2/lib/ruby/3.1.0/csv/parser.rb:332:in `parse'
    from /Users/kyanny/.rbenv/versions/3.1.2/lib/ruby/3.1.0/csv.rb:2365:in `each'
    from /Users/kyanny/.rbenv/versions/3.1.2/lib/ruby/3.1.0/csv.rb:2365:in `each'
    from /Users/kyanny/.rbenv/versions/3.1.2/lib/ruby/3.1.0/csv.rb:1102:in `filter'
    from -e:5:in `<main>'

**options と展開しないといけない(それでも前述の Array インスタンスが渡される問題で実行時エラーになるが)。

echo "a,b\n1,2" | ruby -e 'require "csv"

options = { headers: true, return_headers: true, write_headers: true }

CSV.filter(**options) do |row|
  if row.header_row?
    row << "header3"
    next
  end
  row << "row1_3"
end'
-e:6:in `block in <main>': undefined method `header_row?' for ["a", "b"]:Array (NoMethodError)

  if row.header_row?
        ^^^^^^^^^^^^
    from /Users/kyanny/.rbenv/versions/3.1.2/lib/ruby/3.1.0/csv.rb:1093:in `filter'
    from -e:5:in `<main>'

グラフの種類について

Bizmates Program Level 3 Rank C Lesson 2 より。

ミス洗練の説明。

a. bar graph: to COMPARE two or more pieces of information. (product sales, etc.)

棒グラフ。二つ以上の値を比べるときに使う。

一番基本的なグラフ、だと思う。Excel とかでグラフを自動生成するとこれが選ばれることが多そう。

b. multiple line graph: COMPARE the relationship of two pieces of information. (sales vs time, temperature, etc.)

折れ線グラフ。二つ以上の値の関係を比べるときに使う。

棒グラフとの違いは、おそらく「関係性」に注目するとき折れ線グラフを使う。システムメトリクス(CPU・メモリ使用率)などはたいていこれが使われる。「システム運用アンチパターン」の 4.2.1 では「迷ったら折れ線グラフを使え」とあった。

と思ったが検索して調べてみると、折れ線グラフは「時系列での変化をみる」場合に使うものらしい。

関連で「積み上げ折れ線グラフ」というのも割とよく見る。

c. pie chart: to SHOW how a WHOLE quantity is broken into PARTS. (market share, customer groups, ratings, etc.)

円グラフ。全体に占める割合をみるときに使う。

円グラフは色々な理由で良くない、使うべきではない、という言説を割とよく見かける気がするが、詳細を覚えてない。

d. horizontal bar graph: same as a bar graph but gives MORE SPACE for text.

横棒グラフ。棒グラフの棒が横に伸びてるやつ。普通の棒グラフを「縦棒グラフ」と呼ぶことも。縦棒グラフに比べて文字を書くスペースが広い。

英語は左から右に文字を書くのでグラフについての説明を書くとき棒グラフが横長の方が縦長より文字を書きやすい。あと、パソコンの画面はたいてい横長なので、それもあって縦棒より横棒の方が文字を書きやすい、ということかね、とレッスンで話した。

e. stacked bar chart: to COMPARE the parts to a WHOLE between several categories.

積み上げ棒グラフ。データをいくつかのカテゴリに分けて、全体の中での割合をみる。

これ各棒グラフの全体の長さが全部同じやつとそうでないやつがある気がする。長さが同じやつは円グラフの見せ方を変えて並べるのと意味的には同じ?なので「全体に占める割合」であってそうだけど、長さが違うやつはどちらかというと「各カテゴリの値の推移をみる」ときに使ってそう。ぱっと見の印象より複雑なグラフだと思う。

f. Venn diagram: to show all possible logical relations between sets of items (statistics, probability)

ベン図。集合の関係や論理演算を表すのに使う。苦手意識がある。

g. scatter plot: to show the RESULTS of a collection of points. (results of surveys)

散布図。↑って説明されたけど、検索すると「データの相関関係をみる」ときに使う、とある。

機械学習とかでよく出てくる。点の中央を通る線を引いて、ってやつ。正直、自分で使える気がしない。

h. radar chart: to compare three or more quantitative variables. (quality measurements, skill measurements)

レーダーチャート。radar = レーダー。複数のデータを比較し、傾向をみる。

これはよく見る。ゲームのキャラクターの能力とか、そういう文脈でよく見る。

棒グラフと横棒グラフの違い

"graph" と "chart" という単語の使い分けについて

「graphs は numerical 数字に意味があるときに使うかなあ、charts はカテゴリ・分類に意味があるとき、例を見るとわかるように」じゃあ、pie chart とはいうけど pie graph とは言わない、みたいな?「そうそう。pie graph とは言わないわね」

by ミス洗練

「graph は line で表現されるものを表し、chart は ecclosed area で表現されるものを表すことが多いですね。でも、この違いは深く意識する必要はありません。英語的にはどちらの単語を使っても良い、入れ替え可能です」

by ミスター保護猫

Bizmates Program: Level 3 Rank C Lesson 3: Introducing a chart

ミスターヒップホップと。ノート PC に外部ディスプレイを繋いで、おそらく外部ディスプレイ側にもウェブカメラを付けているようで、レッスン開始時にカメラの位置が違ってて調整したりしてた。「よう、今日はどうだった?」いやあ、、いい日ではなかったです。「どうした?言ってみろ」以下、仕事でちょっと嫌なことがあって、、という愚痴を延々聞いてもらう。じっくり聞いてもらったあと、彼が昔顧客対応の仕事をしてたときのチームメイトの話をしてくれた。曰く、その人がトレーニングを受けて現場に配属になったその日、仕事が終わると泣いていて、明日辞めるという。トレーニングで色々学んだのに何一つ仕事で活かせなくて、何から何まで聞くばかりで、自分が馬鹿みたいに感じたから、と。同僚みんなで励まして、翌日会社にきたがまた泣いた。しかしその翌日は泣かなかった。金曜には笑っていた。そして三ヶ月後、最優秀従業員として表彰された。表彰のくだりはパフォーマンス悪い人をあえて取り立てることで士気高揚を狙うのが常套手段だからなァと思いつつも、落ち込んでる俺を励ますつもりでこの話をしてくれたことはありがたかった。その後、多分前にも彼から教えられたけど、おすすめの本を二冊紹介された。前は日本語版を探しても Kindle 版がなくて買わなかったんだったかなあ。リーダーシップとかの本だからまあいいか、と思ったのだったか。改めてチェックしてみよう。

残り 10 分くらいから Lesson 3 の続き。Try からだったが、See パートの復習から入って、ここが割とわかってなかった・腹落ちしてなかったのか、説明に悩みながらだったので結構時間を使った。質問の意図もすぐには理解できず、やっぱり今日は調子悪いダメな日だなあと実感。Try に入ったのは残り三、四分くらいからで、三つあるグラフのうち二つ目まで説明して終わり。二つ目の棒グラフでは、グラフの要素の説明に続けてうっかり内容の説明もしてしまって、「それはまだこのパートでは触れない内容だぜ」とツッコミ。この手のプレゼン慣れしてないのでなあ。

Lesson 3 の Try の 2 つめのグラフまで終わり、次は三つ目のグラフから。明日は、、ちょっと気持ちが疲れてるので、久しぶりにミスターサーヴェロで Assist Lesson を予約した。ツール・ド・フランス見てる?って雑談をして気分転換しよう。明日はいい日になりますように。

Bizmates Program: Level 3 Rank C Lesson 3: Introducing a chart

ミスター保護猫と。「今日はどんな日でしたか?」あんまりいい日とは言えませんでした、仕事に必要な内部システムが不安定で、リクエストがタイムアウトするので何度もやり直しをしなくちゃいけなくて。それから、自社製品の機能と社外製品との連携に関する質問を受けたのだけど、その外部製品について全く知らないので、明日は調査に難儀しそうで。「明日はいい日になることを願います、何か質問は?」この前話してた、友達が猫の避妊手術を格安で引き受けてくれる獣医さんを紹介してくれるって話はどうなりました?「それが、車のトラブルでピックアップが延期になりました。別の問題もあって、彼(獣医?)に連絡をとっているのだけど電話もメールも繋がらないんです。ひょっとすると今はあの猫たちを自宅のあたりに置いておくほうがいいかもしれません」その人、急用でもできたんですかね「どうだろう、彼はコールセンターで働いてて、自宅でも働いているのだけど(てことは彼 = 友人?)」猫が安全であることを願います「私もです」と雑談はここで終わって、初のレッスンへ。

Lesson 2 の Act から。特にグラフを何個選びなさいとかは言われなかったけど、Video Lesson では三つ選んで説明せよとあったし、予習でも三つ選んでいたので三つ説明した。bar graph は問い合わせ数、pie chart は顧客満足度のスコア別割合、mutiple/stacked line chart はシステム性能メトリクスの表示、など。慣れてる分野の話でもいざ説明しようとすると単語や言い回しがうまく出てこない。

何か質問は?に、前のトレーナーにも質問したんだけど graph と chart ってどう違うの?どう使い分けるの?最初は質問が正しく伝わってなくて、「グラフやチャートは必ずしも必要ではありません、特定のシナリオを表現したい場合に使うと良い」どの図を graph と呼び、どの図を chart と呼ぶのか?「graph は line で表現されるものを表し、chart は ecclosed area で表現されるものを表すことが多いですね。でも、この違いは深く意識する必要はありません。英語的にはどちらの単語を使っても良い、入れ替え可能です」と。人によってニュアンスや答えが違うこういう質問は面白い。

Lesson 3 に移って、この人は最初に Biz Tips を読むタイプなのかな?Biz Tip を読んで「これをあなた自身の理解と言葉に基づいて説明してみてください」その後 See パートを読んで、「このテキストを読んでどう思いますか?your observation について教えてください」で色々と喋る。ここまでで時間切れ。「時間があればこのトピックをもっと深く話し合いたかったのですが」

この人は結構頻繁に言い間違い(文法ミス)を訂正してくるタイプで、このタイプは苦手意識があって避けがちだったので久しぶりに遭遇してちょっと苦労している。テンポがガクンと落ちるし、かなり気にしなくなってきたとはいえやはりリアルタイムで指摘されると若干意気は沈むので、連続して食うとだんだん勢いとか元気がなくなっていくのが自分でもわかる。怖い、というほど大袈裟ではないが喋ることに身構えてしまう感じに無意識になるので、うーん。訂正されなくなるように頑張って受け続けたほうがいいのかなあ。訂正なしだと楽なので負荷が十分かかっていないとは言えるだろうが。続けるために他のあらゆるハードルをできるだけ低くする、という方針でずっとやってきたからなあ。

Lesson 3 の See まで終わり、次は Try から、かな。明日はミスターヒップホップを予約した。

  • I had a little frustration at work.
  • It may take some time.
  • Rectify - fix.
  • From the past.
  • What I could do at that time was to keep retrying..
  • I'm expecting to have a hard time.
  • The sun will rise again.
  • Our system automatically sends a survey to the customer upon ticket completion.
  • We try to understand the customer server's situation.
  • Not everyone understands / can understand..
  • What the graph is representing.