子供の落書き帳 Renaissance
2024-03-18T01:56:37+09:00
soratokimitonoaidani
Hatena::Blog
hatenablog://blog/10257846132609813374
英検準1級に合格した
hatenablog://entry/6801883189091617340
2024-03-18T01:56:37+09:00
2024-03-18T01:56:37+09:00 英検準1級に合格した 2023年第3回試験 1月21日(日)1次試験 3月3日(日)2次試験 3月12日〜 合否発表(ネット上) というわけで確認したら受かってました。 結果 1次試験 2次試験 これからどうする? 結果 特にリーディングは700/750って書いてあるから、CEFRのC1レベルに届いているな。 (準1級だとC1達成と判定しないので、結果ページのCEFRではB2ってことになっているが……) B2の下限が英検CSEスコア2300、C1の下限が2600。俺の現在スコアが2487(下限+187点)。 ということはB2の中でも下から6割くらいのところか。 1次試験 筆記試験90分の時間配…
<p>英検準1級に合格した</p>
<p>2023年第3回試験<br/>
1月21日(日)1次試験<br/>
3月3日(日)2次試験<br/>
3月12日〜 合否発表(ネット上)<br/>
というわけで確認したら受かってました。</p>
<ul class="table-of-contents">
<li><a href="#結果">結果</a></li>
<li><a href="#1次試験">1次試験</a></li>
<li><a href="#2次試験">2次試験</a></li>
<li><a href="#これからどうする">これからどうする?</a></li>
</ul>
<h2 id="結果">結果</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20240318/20240318014814.png" width="944" height="660" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>特にリーディングは700/750って書いてあるから、CEFRのC1レベルに届いているな。
(準1級だとC1達成と判定しないので、結果ページのCEFRではB2ってことになっているが……)</p>
<p>B2の下限が英検<a class="keyword" href="https://d.hatena.ne.jp/keyword/CSE">CSE</a>スコア2300、C1の下限が2600。俺の現在スコアが2487(下限+187点)。<br/>
ということはB2の中でも下から6割くらいのところか。</p>
<h2 id="1次試験">1次試験</h2>
<p>筆記試験90分の時間配分をメモっていたのでここに書いておきます。最初の問題から順に解いています。</p>
<ul>
<li>語彙:14分</li>
<li>大問2(設問31まで):8分(合計22分)</li>
<li>大問3(設問41まで):30分(合計52分) 文章3つのそれぞれを解いたのが合計29分、40分、52分のとき。</li>
<li>英作文開始。YES/NOそれぞれの理由を書き出して、NOで行こうと書き始めたのが16分後(合計68分)</li>
<li>最初の書き出しにだいぶ悩んで、最後に書き終わったのは終了の2分前くらいだった。</li>
</ul>
<p>ただリーディング大得意で読むの速い人の記録なので、もう少し長くかかると思います。
これから受ける人は英作文を早めに書き上げられると良いでしょう。</p>
<h2 id="2次試験">2次試験</h2>
<p>さて2次試験について書いていくが……</p>
<p><a href="https://www.eiken.or.jp/eiken/exam/grade_p1/">英検の公式ホームページ</a>にも2次試験の過去問は掲載されていない。<br/>
第一に質問文を<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C3%F8%BA%EE%B8%A2">著作権</a>の関係でも問題があるし、第二に正確な質問文は覚えていない。日本語でだいたいの意味を書いています。<br/>
(ただ2024年度から試験形式が変わるから、あまり参考にはならないかも?)</p>
<p>着席して軽く話をする。自己紹介は「35歳です、ITエンジニアとしてIT<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%B5%A5%EB%A5%C6%A5%A3%A5%F3%A5%B0">コンサルティング</a>会社で働いています」と喋った。<br/>
2問目で「休日は何をしていますか」と聞かれることに備えて、どう答えようか事前にあれこれ考えていたが、1問目だけで本題の試験に入った。</p>
<p>4コママンガは高層マンションの話。(詳しくは過去問題集を見てください。)</p>
<p>これを2分で説明する。
2コマ目では営業マンが「I can take you to the construction site.」的なセリフを喋っていた。
これを間接話法で話さなければいけないので、とっさには難しい。
「He told them that he can ... he could take them to the construction site.」と一度言い直した。</p>
<p>4コマ目は citizens are against the construction とか言った気がする。
反対するなら「be opposed to the construction」とか使えば良かったな。</p>
<p>ここから質疑応答が4問入る。1問目はお決まりの「4コマ目の登場人物の心情を答えよ」である。 <br/>
……さて、後から振り返ると、これは英検準1級の過去の傾向、典型から外れた、結構イレギュラーな4コママンガである。 <br/>
<a href="https://www.youtube.com/watch?v=tsTA8d3v-aE&t=327s">YouTubeの解説動画</a>を見ると、1コマ目で何か課題が発生します的なことを言っていたと思うけど、今回の1コマ目では明らかに問題は発生していない。<br/>
4コマ目で問題が起きたといえば起きたが、そんなに重大な問題でもない。別に家を購入したわけじゃないんだから、</p>
<p>というわけで試験当時に戻ると、俺は困ってしまった。<br/>
「反対運動なんか知らない、俺は絶対にここに住むんだ」という極端な賛成も「反対運動が起きているから、ここに住むのは絶対に無理だ、諦めよう」という極端な反対も極端な反対も取りにくいな、と思った。<br/>
「ここに住むのは良いと思うが、住民の反対が強いので住むのが難しいのではないか……」的などっちつかずなことを言った。</p>
<p>第2問。
インターネット上のコンテンツは人々がものを買うことに影響しているか、じゃなかったっけ?<br/>
これはYESが答えやすいでしょう。</p>
<ul>
<li>インターネット上には多くの広告がある</li>
<li>人々は多くの広告を普段目にしているので、ものを買う上でそれらを参考にする</li>
<li>また口コミサイトも多くあるので、これもものを買う上で他の人の意見を参考にする</li>
</ul>
<p>的なことを言おうとしたが、「参考にしている」が全然出てこなくてだいぶ詰まった。</p>
<p>第3問。
最近の若者が政治に関わっているかだね、確か。</p>
<p>なぜか咄嗟にグレタ・トゥーンベリが思い浮かんだので、YESで。</p>
<ul>
<li>今日は世界的な課題が多くある、例えば大気汚染や難民など。</li>
<li>これらの課題を解決するためには政治的な取り組みが必要である。</li>
<li>若者はこれらの課題を解決すべきだと訴えている。また政治家にもアピールしている。</li>
</ul>
<p>LOGOPHILIAの単語帳で見た「take to the streets」(街頭デモを行う)を使おうとしたが、間違って「take out to the streets」って言った気がする。</p>
<p>第4問。
都会に農業地帯を増やすべきか、だったと思う。</p>
<p>agricultural という単語が聞こえたので農地のことだとは思ったが、咄嗟に論説が組み立てられなくて、ただの緑地として答えてしまった。<br/>
都会の人間はストレスが溜まってるから緑を見てリラックスできるので、緑地……and agricultural areaを増やすべきだ、と最後で強引に軌道修正した。</p>
<h2 id="これからどうする">これからどうする?</h2>
<p>次は英検1級……だがそのハードルは結構高そう。</p>
<ul>
<li>リーディング
<ul>
<li>の中の単語(語彙)。これはもう単語帳を頑張れということしかない。
<ul>
<li>「でた単」のアプリやる? いやでもあのアプリ、準1級を少し使ったけど、単語の日本語の意味の書き方に引っかかることが多かったんだよな……</li>
<li>パス単は単語レベルが簡単になってしまった的な話を聞くので、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B8%A5%E3%A5%D1%A5%F3%A5%BF%A5%A4%A5%E0%A5%BA">ジャパンタイムズ</a>社の問題集か、EXか、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AD%A5%AF%A5%BF">キクタ</a>ンか……あれ結構種類があるな。</li>
<li>過去記事で書いた通り、私は英単語をフレーズで覚えるのが大好きなので、これの1級のバージョンが出ないか期待している。</li>
</ul>
</li>
<li>それ以外の読解力については心配してないです。英語を読むのは早い自信があるし、内容の把握もほぼ間違えないだろう。</li>
</ul>
</li>
<li>リスニング
<ul>
<li><a class="keyword" href="https://d.hatena.ne.jp/keyword/TOEIC">TOEIC</a>でやってたから余裕だろと思ったら今回ボコボコにされた。</li>
<li>一発で聞き取って内容を把握する</li>
</ul>
</li>
<li>ライティング
<ul>
<li>要対策だと思うけど</li>
</ul>
</li>
<li>スピーキング
<ul>
<li>一番苦手……</li>
<li>やはりこれは日常生活の中で英語を喋る機会がないと言うことに尽きる。なので機会を作らなければならない。</li>
<li>準1級の前はDMM英会話をやったけど、少しやったら飽きてしまった。</li>
</ul>
</li>
</ul>
<p>英検1級に本当に受かりたかったら全体的に底上げが必要だと思うけど、なんとなく単語帳だけやってしまって試験の日を迎えるような気がしてならない。
<div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4789018490?tag=limk-22&linkCode=osi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/5131aVNxYpL._SL500_.jpg" class="hatena-asin-detail-image" alt="出る順で最短合格!英検®1級単熟語EX 第2版 (出る順で最短合格シリーズ)" title="出る順で最短合格!英検®1級単熟語EX 第2版 (出る順で最短合格シリーズ)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4789018490?tag=limk-22&linkCode=osi&th=1&psc=1" target="_blank" rel="noopener">出る順で最短合格!英検®1級単熟語EX 第2版 (出る順で最短合格シリーズ)</a></p><ul class="hatena-asin-detail-meta"><li><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B8%A5%E3%A5%D1%A5%F3%A5%BF%A5%A4%A5%E0%A5%BA">ジャパンタイムズ</a>出版</li></ul><a href="https://www.amazon.co.jp/dp/4789018490?tag=limk-22&linkCode=osi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>ちなみに準1級の過去問は↓を使っていました。<br/>
<div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4053058260?tag=limk-22&linkCode=osi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/41IyCBThknL._SL500_.jpg" class="hatena-asin-detail-image" alt="2024年度 英検準1級過去問題集" title="2024年度 英検準1級過去問題集"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4053058260?tag=limk-22&linkCode=osi&th=1&psc=1" target="_blank" rel="noopener">2024年度 英検準1級過去問題集</a></p><ul class="hatena-asin-detail-meta"><li>学研プラス</li></ul><a href="https://www.amazon.co.jp/dp/4053058260?tag=limk-22&linkCode=osi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div>
それでは。</p>
soratokimitonoaidani
2023年に買ってよかったもの
hatenablog://entry/6801883189079046515
2024-01-29T22:53:31+09:00
2024-01-29T22:53:31+09:00 2023年に買ってよかったもののメモ。あんまり多くない気がする。 Shokz OpenRun Pro 骨伝導イヤホン VOLTRX 電動プロテインシェイカー VALX プロテイン ランニングポーチ SUZURI ドライTシャツ ワークマン ボアフリースカーディガン 総評:やっぱり少ないな Shokz OpenRun Pro 骨伝導イヤホン 一番はこれだろう。7月のAmazon大規模セールにつられて購入。 今まで有線のイヤホンでリモートワークの会議に参加していたが、パソコンの前にいる必要がなく自由に動けるようになったのは良い。音質も聞きやすい。口の前にマイクはないのだが、ちゃんと話もできる。 ジ…
<p>2023年に買ってよかったもののメモ。あんまり多くない気がする。</p>
<ul class="table-of-contents">
<li><a href="#Shokz-OpenRun-Pro-骨伝導イヤホン">Shokz OpenRun Pro 骨伝導イヤホン</a></li>
<li><a href="#VOLTRX-電動プロテインシェイカー">VOLTRX 電動プロテインシェイカー</a></li>
<li><a href="#VALX-プロテイン">VALX プロテイン</a></li>
<li><a href="#ランニングポーチ">ランニングポーチ</a></li>
<li><a href="#SUZURI-ドライTシャツ">SUZURI ドライTシャツ</a></li>
<li><a href="#ワークマン-ボアフリースカーディガン">ワークマン ボアフリースカーディガン</a></li>
<li><a href="#総評やっぱり少ないな">総評:やっぱり少ないな</a></li>
</ul>
<h2 id="Shokz-OpenRun-Pro-骨伝導イヤホン">Shokz OpenRun Pro <a class="keyword" href="https://d.hatena.ne.jp/keyword/%B9%FC%C5%C1%C6%B3">骨伝導</a>イヤホン</h2>
<p>一番はこれだろう。7月の<a class="keyword" href="https://d.hatena.ne.jp/keyword/Amazon">Amazon</a>大規模セールにつられて購入。<br/>
今まで有線のイヤホンでリモートワークの会議に参加していたが、パソコンの前にいる必要がなく自由に動けるようになったのは良い。音質も聞きやすい。口の前にマイクはないのだが、ちゃんと話もできる。<br/>
ジョギングとの相性も良い(耳をふさがないので、車の音なども聞こえる)。<br/>
ただ寝転んだ場合の相性は悪い(頭の後ろが当たるので)。</p>
<p>……そういえば有線で良いイヤホン買ってないな……(Ultimate Ears UE900sは断線で壊れてしまった。あと<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%BC%A5%F3%A5%CF%A5%A4%A5%B6%A1%BC">ゼンハイザー</a>のIE60はここ数年間行方不明だ。どこ行ったんだろう……)</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B09LQVQJF1?tag=limk-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/31MU1ckTv9L._SL500_.jpg" class="hatena-asin-detail-image" alt="Shokz OpenRun Pro 骨伝導イヤホン 最新骨伝導技術 低音再生強化急速充電 DSPノイズキャンセリング・マイク 10時間の音楽再生と通話 公式ストア正規品 ワイヤレス 防水 bluetooth5.1 ブラック" title="Shokz OpenRun Pro 骨伝導イヤホン 最新骨伝導技術 低音再生強化急速充電 DSPノイズキャンセリング・マイク 10時間の音楽再生と通話 公式ストア正規品 ワイヤレス 防水 bluetooth5.1 ブラック"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B09LQVQJF1?tag=limk-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">Shokz OpenRun Pro 骨伝導イヤホン 最新骨伝導技術 低音再生強化急速充電 DSPノイズキャンセリング・マイク 10時間の音楽再生と通話 公式ストア正規品 ワイヤレス 防水 bluetooth5.1 ブラック</a></p><ul class="hatena-asin-detail-meta"><li>SHOKZ</li></ul><a href="https://www.amazon.co.jp/dp/B09LQVQJF1?tag=limk-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<h2 id="VOLTRX-電動プロテインシェイカー">VOLTRX 電動<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C6%A5%A4%A5%F3">プロテイン</a>シェ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%AB">イカ</a>ー</h2>
<p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C6%A5%A4%A5%F3">プロテイン</a>を飲み始めたときに、自分で混ぜなければいけないのに面倒くさくなって電動シェ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%AB">イカ</a>ーを購入。<br/>
(自分で振るシェ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%AB">イカ</a>ーをすっ飛ばして、いきなり電動シェ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%AB">イカ</a>ーを買った)<br/>
ボタンを押すだけなので楽。<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C6%A5%A4%A5%F3">プロテイン</a>の粉がきれいに溶ける。<br/>
ただ、物持ちは悪い。2022年末に購入して、数ヶ月したらボタンを押さなくても勝手にスイッチがオンになって「ブーン」と音を立てるようになってしまった。その後、最近は完全に壊れて電動部分が全く動かなくなった。捨てて次を買おう……<br/>
考えてみると、これはコップの一種なので水を入れたり洗ったりして濡れることが多い。そして、充電式なのでUSB Type-Cで充電する必要がある。当然、ちゃんと乾かしてから充電するようにすれば問題ないのだろう。しかし、面倒くさがりの俺には無理だった……</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B09LZ5XTPV?tag=limk-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/41iwhG6jiTL._SL500_.jpg" class="hatena-asin-detail-image" alt="VOLTRX 電動シェイカー - VortexBoost プロテインシェイカー ミキサー - USB C 充電 プロテイン シェイカー - BPAフリー、防水、カラフルなライトショー、600ml(オーロラグリーン)" title="VOLTRX 電動シェイカー - VortexBoost プロテインシェイカー ミキサー - USB C 充電 プロテイン シェイカー - BPAフリー、防水、カラフルなライトショー、600ml(オーロラグリーン)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B09LZ5XTPV?tag=limk-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">VOLTRX 電動シェイカー - VortexBoost プロテインシェイカー ミキサー - USB C 充電 プロテイン シェイカー - BPAフリー、防水、カラフルなライトショー、600ml(オーロラグリーン)</a></p><ul class="hatena-asin-detail-meta"><li>VOLTRX</li></ul><a href="https://www.amazon.co.jp/dp/B09LZ5XTPV?tag=limk-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<h2 id="VALX-プロテイン">VALX <a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C6%A5%A4%A5%F3">プロテイン</a></h2>
<p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C6%A5%A4%A5%F3">プロテイン</a>の方はもっぱらVALXを買っている。<br/>
公式サイトで毎月末にセールしているので、無くなってきたら4つセットで買うことにしている。<br/>
最初に買ったGronGがあまりにもまずかったので、色々調べたりしてここにたどり着いた。<br/>
個人的にはどの味を買っても美味しくてハズレがない。<br/>
と思うが、動画とかを見ているとまずいって言ってる人もいる模様。個人によって感じ方に差があるようなので自分にあった<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C6%A5%A4%A5%F3">プロテイン</a>を見つけるしかないね。</p>
<p>最初に飲むならカフェオレ味が無難な気がする。<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C6%A5%A4%A5%F3">プロテイン</a>っぽさが無くて普通のカフェオレと思って飲める。<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%ED%A5%A4%A5%E4%A5%EB%A5%DF%A5%EB%A5%AF%A5%C6%A5%A3%A1%BC">ロイヤルミルクティー</a>とか抹茶も好き。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B08WRHBW4W?tag=limk-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/41Bd89GH8dL._SL500_.jpg" class="hatena-asin-detail-image" alt="VALX バルクス ホエイ プロテイン カフェオレ風味 ぷろていん ホエイプロテイン Produced by 山本義徳 1kg 国内製造" title="VALX バルクス ホエイ プロテイン カフェオレ風味 ぷろていん ホエイプロテイン Produced by 山本義徳 1kg 国内製造"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B08WRHBW4W?tag=limk-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">VALX バルクス ホエイ プロテイン カフェオレ風味 ぷろていん ホエイプロテイン Produced by 山本義徳 1kg 国内製造</a></p><ul class="hatena-asin-detail-meta"><li>VALX</li></ul><a href="https://www.amazon.co.jp/dp/B08WRHBW4W?tag=limk-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<h2 id="ランニングポーチ">ランニングポーチ</h2>
<p>ランニングするときにポケットにケータイ入れてると揺れて落ちそうで怖いな……ということで購入。<br/>
<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>と鍵と<a class="keyword" href="https://d.hatena.ne.jp/keyword/Suica">Suica</a>を入れる。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B0998K1DFL?tag=limk-22&linkCode=osi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/31NZn4wcfrL._SL500_.jpg" class="hatena-asin-detail-image" alt="【日本代表選手が愛用】ランニング ポーチ ウェストポーチ TRAN 伸縮大容量 フィットして揺れにくい スマホ収納 イヤホン穴 鍵入れ・カード入れ別収納 ジョギング・マラソンに便利" title="【日本代表選手が愛用】ランニング ポーチ ウェストポーチ TRAN 伸縮大容量 フィットして揺れにくい スマホ収納 イヤホン穴 鍵入れ・カード入れ別収納 ジョギング・マラソンに便利"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B0998K1DFL?tag=limk-22&linkCode=osi&th=1&psc=1" target="_blank" rel="noopener">【日本代表選手が愛用】ランニング ポーチ ウェストポーチ TRAN 伸縮大容量 フィットして揺れにくい スマホ収納 イヤホン穴 鍵入れ・カード入れ別収納 ジョギング・マラソンに便利</a></p><ul class="hatena-asin-detail-meta"><li>TRAN(トラン)(R)</li></ul><a href="https://www.amazon.co.jp/dp/B0998K1DFL?tag=limk-22&linkCode=osi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<h2 id="SUZURI-ドライTシャツ">SUZURI ドライTシャツ</h2>
<p><a href="https://suzuri.jp/Rumiko-koyama/3889449/dry-t-shirt/s/lightyellow">犬たくさん バックプリント</a><br/>
<a class="keyword" href="https://d.hatena.ne.jp/keyword/DDR">DDR</a>するときはだいたいこれ。汗でびしょ濡れになってもすぐに乾く。<br/>
面白いデザインのドライTシャツ出てこないかな。</p>
<h2 id="ワークマン-ボアフリースカーディガン">ワークマン ボアフリースカーディガン</h2>
<p>最後は貧乏くさいやつだが……<br/>
サンシャイン池袋に「ワークマン女子」があって、出かけたついでに寄ってみたらフリースが980円でびっくりしたので買ってしまった。<br/>
これが1000円を切るってどうなってるんだ。ワークマン恐るべし。家で着ているが、暖かくて良い。<br/>
商品ページが見つからなかったので、紹介記事の方でリンクを張っておく。<br/>
<a href="https://www.roomie.jp/2023/11/1108863/">ワークマンで買える「ボアフリースカーディガン」が、想像以上の快適さだった。コレで980円はさすがすぎる…</a></p>
<h2 id="総評やっぱり少ないな">総評:やっぱり少ないな</h2>
<p>ちゃんと不便や必要性を察知して「これを買おう」と決める力が弱い気がする。<br/>
面倒くさがりだからそういう意思決定を避けてしまうのであった。<br/>
年間の収支は結構なプラスだったし(マネー<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D5%A5%A9%A5%EF">フォワ</a>ードの記録を見た)、もっと積極的に新しいガジェットとかを買ってもいいと思うんだよな。
毎月1万円とか5千円を新しいものを買うのに強制的に充てるとかしたほうが良いのか……<br/>
しかし問題は何を買うかよな。例えば<a class="keyword" href="https://d.hatena.ne.jp/keyword/YouTube">YouTube</a>で「買ってよかったもの」で検索するとたくさん出てくるけど、それが俺に合うかは分からないわけだし。<br/>
さてどうしたものか……みんなどうしてるんやろ?<br/>
それでは。</p>
soratokimitonoaidani
2023年の振り返り
hatenablog://entry/6801883189075411132
2024-01-16T02:47:36+09:00
2024-01-24T01:21:08+09:00 2023年振り返り。
仕事、一人暮らしの生活、自己学習、英語、音ゲーなど。
<h2 id="2023年振り返り">2023年振り返り</h2>
<ul class="table-of-contents">
<li><a href="#2023年振り返り">2023年振り返り</a></li>
<li><a href="#仕事">仕事</a></li>
<li><a href="#一人暮らし">一人暮らし</a></li>
<li><a href="#自己学習">自己学習</a><ul>
<li><a href="#connpassのイベントの話">connpassのイベントの話</a></li>
<li><a href="#英語だけはやり始めた話">英語だけはやり始めた話</a></li>
</ul>
</li>
<li><a href="#ゲーム">ゲーム</a><ul>
<li><a href="#音ゲー">音ゲー</a></li>
<li><a href="#音ゲー以外">音ゲー以外</a></li>
</ul>
</li>
<li><a href="#ポエム">ポエム</a></li>
<li><a href="#総評">総評?</a></li>
</ul>
<p>1月も気づけばあっという間に半分が終了してしまった。<br/>
忘れないうちに2023年の振り返りをしよう。</p>
<p>2022年版はこちら。<br/>
<a href="https://linus-mk.hatenablog.com/entry/2023/01/02/234922">2022年の振り返り - 子供の落書き帳 Renaissance</a></p>
<p>※ 今年・去年・来年がややこしくなりそうなので、2023年・2024年で表記を統一します。</p>
<h2 id="仕事">仕事</h2>
<p>2023年はずっと1つのプロジェクトに従事していた。
12月にリリース・本番稼働ができて、良かったね……と、少なくとも表面的には言えるだろう。
だが本当にうまくやれただろうか。</p>
<p>リリース・本番稼働に向けた各段階において、起こり得る問題を先回りして特定し、関係する他のチームの人たちと適宜相談して課題を解決できた。<br/>
色々なところから飛んできた調査依頼や相談については、丁寧に応対してきたし、それによってプロジェクトが前に進むことに貢献できたという自負はある。</p>
<p>じゃあ、何で自分のところの仕様に詳しいのかと考えると、何というか「そのチームに長く在籍しているから」なのだ。
そりゃ長いことその部分に関与してきて、ずっとやっていれば詳しくもなるだろうという当然の道理である。<br/>
ちゃんと自分の理解を、他のチームにも分かるようにドキュメントや仕様書として残すべきだったのだが、
納期に間に合わせるためにドキュメント化は犠牲になったのである。
去年の仕事の心残りは、ドキュメントがボロボロだったこと、この1点に尽きる。<br/>
自分の強みは、複雑な事柄を読み解いて、他の人にも分かるような適切な形で整理することだと思っている。
その強みがフロー(日々のSlackのやり取り)では活きたものの、永続的なストック(各種ドキュメント)に強みを活かすことが少なかったのは、まぁまぁフラストレーションになっている。</p>
<p>他チームが(俺のチームの担当部分を含む全体の仕様を整理するために)俺のチームの範囲の動作仕様を整理した図を作っていたのとか、恥でしょ。
我々が職務怠慢をしていて他のチームに肩代わりしてもらったことの証左なんだから。今思い出したって忸怩たる気分だ。
というか、ドキュメント不足のせいでどういう仕様なのか俺自身でさえ把握できていない箇所があるしな。</p>
<p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Python">Python</a>のコードを自分自身が書くことは殆ど無くなって(少しはある)、人のコードをレビューするのが多くなった。<br/>
じゃあプロジェクトマネジメントやチームリーディングを担当しているかというと、そういうわけでも無いし、自分の担当している業務がうまく表現できなくて、いつももどかしい気分になる。<br/>
自チームで作っているシステムについて何でもやります、というのが正しい気がしている。</p>
<h2 id="一人暮らし">一人暮らし</h2>
<blockquote><p>面倒くさがりな性格のせいで、「一応生きていくことはできるが、使いにくくて不便」という状況になっているので、どうやって住みやすい暮らしにすれば良いかな……</p></blockquote>
<p>一人暮らしして1年半、この状態が継続中……生活力が皆無であることが露呈するのであんまり具体的には言えないけど。<br/>
あと、一人暮らしを脱出できなかったわ。</p>
<h2 id="自己学習">自己学習</h2>
<p>2023年も2022年に続いてほとんどやらなかったなぁ……。</p>
<p>ブログに技術的な内容で書いたのは、この2個か。</p>
<ul>
<li><a href="https://linus-mk.hatenablog.com/entry/dask_query_variable_name">daskのquery関数で変数名を指定する方法</a></li>
<li><a href="https://linus-mk.hatenablog.com/entry/docker_image_prune_until">docker image pruneで「何日前より前のイメージを全て削除」を指定する</a></li>
</ul>
<p>確かにこの2つは実際の業務で詰まったから、調べてまとめたんだよな。今でも思い返すことができる。<br/>
他の点は行き詰まることが無かったのか……というと、そういう訳では無い。<br/>
課題は他にもまだまだあったが、課題の抽象度が上がって、上記2つのような具体的なものとして指し示すことができなくなった。<br/>
こにふぁーさんの<a href="https://konifar-zatsu.hatenadiary.jp/">Konifar's ZATSU</a> みたいな感じで、うまく抽象化して書くのが良いのかなぁ……</p>
<h3 id="connpassのイベントの話">connpassのイベントの話</h3>
<p>年末に、同僚が「connpassなどの外部の勉強会に積極的に参加している」という話をしていた。
まず第一に「勉強熱心ですごいなぁ」と思ったが、その次に「もっと早く知りたかったなぁ」と思った。
(別に個々のイベントの内容を全部知りたいわけではなくて、(俺を含む)周りの人を感化することができたんじゃないか、的な。)</p>
<p>会社内の周囲の人たちが、(仕事以外に)どういう技術的な活動をしていて、どういうことに興味があるか、が見えにくい。<br/>
俺、チーム、プロジェクト、顧客、以上。って感じだわ。</p>
<p>さりとて、どのイベントに行くかって考えると、難しくないかなぁ。
<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A1%BC%A5%D7%A5%E9%A1%BC%A5%CB%A5%F3%A5%B0">ディープラーニング</a>を業務で使っているわけでもないし。<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%B3%D8%BD%AC">機械学習</a>じゃないデータ分析系ってあんまりイベントにならない気がするし。
ん〜〜、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Python">Python</a>の書き方とかシステム構築の一般論とかそのへんだろうか。</p>
<h3 id="英語だけはやり始めた話">英語だけはやり始めた話</h3>
<p>11月あたりから急に英語をやりだした。<br/>
きっかけはおそらく、ふるやん(@furuya1223)さんが<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B4%C1%B8%A1">漢検</a>1級を取ったことだと思う。
<a href="https://www.creativ.xyz/kanken-1k/">https://www.creativ.xyz/kanken-1k/</a></p>
<p>(俺自身が<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B4%C1%B8%A1">漢検</a>準1級を10年ほど前に取ったので分かるのだが)<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B4%C1%B8%A1">漢検</a>1級は準1級とは別格の難しさがある。
その割に取っても使い所が殆ど無いという資格である。
あれを1年くらい? それ以上? 長期間にわたって継続して勉強して合格まで行くの、マジすごい。と思った。</p>
<p>俺も何か資格を取るかなーとぼんやり考え始めた。
合格してどれくらい役に立つ/役に立たない目標にしようか色々考えつつ、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B4%C1%B8%A1">漢検</a>1級は無理な気がしたので英語にした。
英語使えたほうが何かと便利だし……(既に役に立つ方を目指そうとしてしまっている)<br/>
<a class="keyword" href="https://d.hatena.ne.jp/keyword/TOEIC">TOEIC</a>満点を目指すのは、意味があんまりない資格なのでそれを目標にしようかな(既に一度975点を取っているので、990点とそう変わらないため)とも思った。
結局、<a class="keyword" href="https://d.hatena.ne.jp/keyword/TOEIC">TOEIC</a>と別の尺度でやってみたら面白そうな気がしたので、英検で。
ライティングとスピーキングなんて普段全くやらないから、これを機にやるのも悪くないだろう。
2024/1/21に英検準1級(1次)を受けます。準1級の後、英検1級を目指すか、<a class="keyword" href="https://d.hatena.ne.jp/keyword/TOEIC">TOEIC</a>満点を目指すかは考え中。</p>
<p>今は英字新聞を読んだり、<a class="keyword" href="https://d.hatena.ne.jp/keyword/YouTube">YouTube</a>で英語のニュースを聞いたりして勉強しているが、
ちょっと前に勉強した単語が別のところで登場しているのを見たりすると、純粋に楽しくて嬉しい。<br/>
やっぱり自分は(ストレングスファインダーでいうところの)学習欲の人間なんだなーと。<br/>
「学習欲」が強い人は、すぐに役立ったりしなくても、何かを学ぶときに楽しくなる、的なことが書いてあった気がする。</p>
<h2 id="ゲーム">ゲーム</h2>
<h3 id="音ゲー"><a class="keyword" href="https://d.hatena.ne.jp/keyword/%B2%BB%A5%B2%A1%BC">音ゲー</a></h3>
<p>2023年にプレイした<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B2%BB%A5%B2%A1%BC">音ゲー</a>は、ほとんどが<a class="keyword" href="https://d.hatena.ne.jp/keyword/DDR">DDR</a>だった。<br/>
<a href="http://skillattack.com/sa4/dancer_skillpoint.php?_=detail&ddrcode=11086793&date=20221226">skill attack 2022末</a><br/>
<a href="http://skillattack.com/sa4/dancer_skillpoint.php?_=detail&ddrcode=11086793&date=20231231">skill attack 2023末</a></p>
<p>レベル14の99万点が1→3譜面、レベル15の99万点が0→1譜面。レベル16の95万点が1→12譜面。
まぁ逆詐称の譜面が新たに増えたという理由も一部あるとはいえ、地力は向上したと思っていいだろうなぁ。</p>
<p>あとはクリア目線、18を弱・中・強の3つに分けたときに弱は大体はクリアできて、中はできたりできなかったり、
クリアできそうでできないのが、Cosy Catastrophe、VOLAQUAS、Triple Journey -TAG EDITION-、このあたり。
というか他の曲はほとんどやってないな。頑張ってクリアするところまで粘着してない。</p>
<p>んー……一応<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C9%A5%E9%A5%DE%A5%CB">ドラマニ</a>も書いておく? でも全然プレイして無かったと思う。<br/>
<a href="http://gsv.fun/ja/highvoltage/897/d">HIGH-VOLTAGE gsv記録</a><br/>
<a href="http://gsv.fun/ja/fuzzup/1168/d">FUZZ-UP gsv記録</a><br/>
新曲を全然詰めてないな。あと旧曲もちゃんとやってないから<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B9%A5%AD%A5%EB%A5%DD%A5%A4%A5%F3%A5%C8">スキルポイント</a>減ってるな。オワタ。</p>
<h3 id="音ゲー以外"><a class="keyword" href="https://d.hatena.ne.jp/keyword/%B2%BB%A5%B2%A1%BC">音ゲー</a>以外</h3>
<p>原神が主。<br/>
螺旋12層が全然できないのが悩み。多分適当にやっているから戦闘スキルが低い。</p>
<h2 id="ポエム">ポエム</h2>
<p>最近、ぼんやりと「もう少しあの活動に時間と労力をかけていれば、もっと結果を出せていたのかもしれないな」と思うことが多い。
簡単に言えば時間配分の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C8%A5%EC%A1%BC%A5%C9%A5%AA%A5%D5">トレードオフ</a>というやつだ。<br/>
「あの活動」に入るのは、だいたいちょっと取り組んだこと、多分<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B2%BB%A5%B2%A1%BC">音ゲー</a>(<a class="keyword" href="https://d.hatena.ne.jp/keyword/DDR">DDR</a>)とAI画像生成(Stable Diffusion他)である。<br/>
技術的な取り組みが「あの活動」に代入されることがない時点でどうなのよ感がある。結構、ある。技術へのコミットメントを増やしたいという課題意識を、そもそも持っていないということなのか……???<br/>
一方で、去年1秒もやらなかったこと、例えば「もう少し将棋に時間をかけて取り組んでいれば……」というふうに考えたことはないな。別に将棋のことは何とも思っていないので。</p>
<p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%B2%BB%A5%B2%A1%BC">音ゲー</a>(<a class="keyword" href="https://d.hatena.ne.jp/keyword/DDR">DDR</a>)が分かりやすくて、去年は<a class="keyword" href="https://d.hatena.ne.jp/keyword/DDR">DDR</a>に集中していたので<a class="keyword" href="https://d.hatena.ne.jp/keyword/DDR">DDR</a>の腕前は伸びたけど、その代償に他の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B2%BB%A5%B2%A1%BC">音ゲー</a>(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C9%A5%E9%A5%DE%A5%CB">ドラマニ</a>とサンボル)は腕が落ちた。なぜならプレイしていないので。<br/>
それでも<a class="keyword" href="https://d.hatena.ne.jp/keyword/DDR">DDR</a>のプレイ頻度はそんなに高くないから、もっとプレイ回数を増やせばもっとうまくなるだろうけど、そうすると他の活動の時間を減らさなければならない。<br/>
まぁ労力を投下したからと言って結果が必ず良くなるとは限らないな。
極端な場合、時間と労力をかけたのに何の成果も得られなかった場合もあるから……(遠い目)</p>
<p>……と言いつつ、ダラダラとゲームしてたら休日が終わったりするんだよな。「ある活動を取って他の活動を捨てる」とかじゃなくて、「何の足しにもならない活動」に時間を割き過ぎている場合がある。<br/>
などと思っていたら、こんな動画が<a class="keyword" href="https://d.hatena.ne.jp/keyword/YouTube">YouTube</a>のレコメンドに上がってきていた。やってみようか?
<a href="https://www.youtube.com/watch?v=dbiNhAZlXZk">Use Strategic Thinking to Create the Life You Want - YouTube</a></p>
<p>あと英語は別に「頑張って歯を食いしばって英語をやっている(=努力して英語学習に時間と労力を費やしている)」わけじゃないんだよな。<br/>
何か面白いから英単語帳を開くし、英字新聞読むし、Ankiで単語帳を進める、とかやってると、気づいたら1日30分とか1時間くらいは英語関連のことをやっている。<br/>
忙しいふりしてたけど、普通に英語学習の時間が割り込んでくる余地あるんじゃん! と自分で自分に驚いているのが1つ。<br/>
あとは、こういう風に気づいたら時間をかけて取り組んでいてスキルが上がるならそれが一番いいよね、というのが1つ。</p>
<p>まぁ子育てしてる人からすれば「独り身のくせに(=自分の時間と財産を全て自分のためだけに使えるくせに)何言ってるんだ」とか言われそうだが。</p>
<p>特に結論はない。強いて言うならば</p>
<ul>
<li>自分自身がどの活動にどの程度、時間と労力を費やしているのかを把握したい</li>
<li>「何の足しにもならない活動」に時間を費やすのをやめたい</li>
<li>こと技術に関しては、「気づいたら時間と労力を費やしていた」になるような仕組み(仕掛け)を作れないかな</li>
</ul>
<p>あたりだろうか。</p>
<h2 id="総評">総評?</h2>
<p>だいたい書きたいことは書けたので完成ということにする。</p>
<p>ひとまず以上です。</p>
soratokimitonoaidani
今までの英語学習と試験結果を振り返る
hatenablog://entry/6801883189069202111
2023-12-23T22:35:20+09:00
2023-12-23T23:45:24+09:00 長文のブログを書く体力と習慣がなくなってしまった…… 最近になってなぜか英語勉強の熱が再燃してきた。 英検準1級の試験に申し込みしてきた。これを期に今までの英語学習を振り返るための記事である。 小学校より前 小学校 中学校 Asahi Weekly K会 PEANUTS / スヌーピー 高校 システム英単語 Z会東大マスターコース 大学〜大学院 TOEIC(2007年?月) TOEFL(2010年5月) TOEIC(2011年11月) 社会人 TOEIC (2013年4月) Anki TestYourVocab 英字新聞 小学校より前 セサミストリートとか見てたと思うけど、詳しいことはもはや覚…
<p>長文のブログを書く体力と習慣がなくなってしまった……</p>
<p>最近になってなぜか英語勉強の熱が再燃してきた。<br/>
英検準1級の試験に申し込みしてきた。これを期に今までの英語学習を振り返るための記事である。</p>
<ul class="table-of-contents">
<li><a href="#小学校より前">小学校より前</a></li>
<li><a href="#小学校">小学校</a></li>
<li><a href="#中学校">中学校</a><ul>
<li><a href="#Asahi-Weekly">Asahi Weekly</a></li>
<li><a href="#K会">K会</a></li>
<li><a href="#PEANUTS--スヌーピー">PEANUTS / スヌーピー</a></li>
</ul>
</li>
<li><a href="#高校">高校</a><ul>
<li><a href="#システム英単語">システム英単語</a></li>
<li><a href="#Z会東大マスターコース">Z会東大マスターコース</a></li>
</ul>
</li>
<li><a href="#大学大学院">大学〜大学院</a><ul>
<li><a href="#TOEIC2007年月">TOEIC(2007年?月)</a></li>
<li><a href="#TOEFL2010年5月">TOEFL(2010年5月)</a></li>
<li><a href="#TOEIC2011年11月">TOEIC(2011年11月)</a></li>
</ul>
</li>
<li><a href="#社会人">社会人</a><ul>
<li><a href="#TOEIC-2013年4月">TOEIC (2013年4月)</a></li>
<li><a href="#Anki">Anki</a></li>
<li><a href="#TestYourVocab">TestYourVocab</a></li>
<li><a href="#英字新聞">英字新聞</a></li>
</ul>
</li>
</ul>
<h2 id="小学校より前">小学校より前</h2>
<p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%BB%A5%B5%A5%DF%A5%B9%A5%C8%A5%EA%A1%BC%A5%C8">セサミストリート</a>とか見てたと思うけど、詳しいことはもはや覚えていない。</p>
<h2 id="小学校">小学校</h2>
<p>英語の勉強らしい勉強をしたのは、小6の最後で中学受験に合格したあとのこと。3日間か5日間だったような。<br/>
いわゆる<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D5%A5%A9%A5%CB%A5%C3%A5%AF%A5%B9">フォニックス</a>(英単語の発音の規則)について教わった。</p>
<h2 id="中学校">中学校</h2>
<h3 id="Asahi-Weekly">Asahi Weekly</h3>
<p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%C4%AB%C6%FC%BF%B7%CA%B9">朝日新聞</a>から発刊されている(英語学習者向けの)英字新聞。多分母親がこの新聞を取ったんだと思う。暇なときに読む、くらいだったけど、読解力の役には立ったと思う。<br/>
そういえば、思い出した。中2のときの先生が「英語の文章をノートに書き写して。写したページ数に応じて得点を与える」という課題を出したことがある。<br/>
で、俺はこのAsahi Weeklyの記事の文章を書き写して提出した。ノートが返却されたときに「君は難しい文章を書いてくれたので、通常の得点の2倍で計算しておきます」という注釈が書いてあって、嬉しかったな。<br/>
むしろ、英字新聞のような書き写すネタが無かった他の人は、何の文章を書いていたんだろうか? 教科書や問題集の文面を書き写すだけだと、飽きると思うけど。</p>
<h3 id="K会">K会</h3>
<p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%B2%CF%B9%E7%BD%CE">河合塾</a>系列の塾。夏期講習などの長期休みだけ参加。<br/>
「英語を学ぶんじゃなくて、英語で学ぶんや!」みたいなコンセプトで、聖書とか<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AE%A5%EA%A5%B7%A5%E3">ギリシャ</a>神話とか、あとはイギリスの歴史とか<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B2%CA%B3%D8%BB%CB">科学史</a>とか、色々な長文を読まされた気がする。何ページも続く英文に抵抗がなくなったのはK会のおかげかもしれない。</p>
<h3 id="PEANUTS--スヌーピー">PEANUTS / <a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B9%A5%CC%A1%BC%A5%D4%A1%BC">スヌーピー</a></h3>
<p>小学校の頃から<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B9%A5%CC%A1%BC%A5%D4%A1%BC">スヌーピー</a>の漫画が好きでよく読んでいたが、中学校に上がって英語で読めるようになると日本語訳と見比べながら読むようになったかな。<br/>
海外の文学作品とかだったら、日本語版には日本語だけが書いてあるけど、PEANUTSはなぜか昔から原文と和訳を併記する形だった。<br/>
(あの独特の書き文字も漫画作品の一部だからかなぁ。日本語版の形式にもよるが、セリフの中の英文はそのままで、枠の外に日本語訳が書いてあることが多い。)<br/>
偶然だけど、好きになった作品が英語の勉強に役立つもので良かった。</p>
<h2 id="高校">高校</h2>
<h3 id="システム英単語"><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%B1%D1%C3%B1%B8%EC">システム英単語</a></h3>
<p>大学受験のときの英単語帳は<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%B1%D1%C3%B1%B8%EC">システム英単語</a>の1冊だけだった。単語はフレーズで覚えると良い、という序文に感銘を受けたことを覚えている。(最新版の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%B1%D1%C3%B1%B8%EC">システム英単語</a>だと序文は違っている。当時の版のもの。)<br/>
この教えに従い、現在に至るまで、単語はフレーズで覚えたい派である。<br/>
しかしフレーズで覚えられるという条件を満たす、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%B1%D1%C3%B1%B8%EC">システム英単語</a>より上のレベルの単語帳を見つけていない……<br/>
誰か「フレーズで覚えるという、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%B1%D1%C3%B1%B8%EC">システム英単語</a>と同形式の単語帳をまとめてレビュー」って記事書いてくれないかな。</p>
<p>受験当時に使っていたのはこの版。 <a href="https://www.amazon.co.jp/gp/product/4796110593/">https://www.amazon.co.jp/gp/product/4796110593/</a></p>
<h3 id="Z会東大マスターコース"><a class="keyword" href="https://d.hatena.ne.jp/keyword/Z%B2%F1">Z会</a>東大マスターコース</h3>
<p>それと、塾は<a class="keyword" href="https://d.hatena.ne.jp/keyword/Z%B2%F1">Z会</a>に通っていた。この記事の中で唯一個人名が出てくるが、柳瀬晃先生である。<br/>
まぁなかなか厳しい先生だった。自作プリントを作って配ることが多く、そのプリント演習でガチで難しい構文の英文和訳を解かされた。その甲斐あって、英文解釈の力はめちゃめちゃに強くなった。自作のプリントは捨てるのも惜しいので未だに取っておいてある。<br/>
「国外留学したこともない俺が英語力で困ることもなくやっていけているのは何故か」といえば、柳瀬先生のおかげであることは間違いない。15年以上経った今でも、いくつかの話は思い出せるもんな……<br/>
「はい、『at the ... of 〜』で『〜を代償・犠牲にして』の意味になる単語4つを答えてもらおうか、では〇〇さんどうぞ」(正解は cost/price/expense/sacrifice)</p>
<p>柳瀬先生は「アラン・ド・ボトン」という小説家が好きらしく、この人の文章から自作プリントを作ることが非常に多い。そういや、この「アラン・ド・ボトン」の小説をいつか読もうと思って、まだ読んでないな……</p>
<p>(柳瀬先生の評判を知りたくてこの記事を読む東<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C2%E7%BC%F5">大受</a>験生はいないと思うが、もしいたら1点だけ注意。英作文については柳瀬先生は全部カットするので、自分でちゃんと対策しましょう。自分でやらなかった俺は試験本番で英作文の2問中1問を空欄で提出してしまった。まぁ、それでも受かったけど。)</p>
<h2 id="大学大学院">大学〜大学院</h2>
<h3 id="TOEIC2007年月"><a class="keyword" href="https://d.hatena.ne.jp/keyword/TOEIC">TOEIC</a>(2007年?月)</h3>
<p>1回公式問題集を解いただけで受験。確か920点。<br/>
すっかり拍子抜けした俺は「はーん、<a class="keyword" href="https://d.hatena.ne.jp/keyword/TOEIC">TOEIC</a>なんて簡単じゃねーか」という気持ちになった。</p>
<h3 id="TOEFL2010年5月"><a class="keyword" href="https://d.hatena.ne.jp/keyword/TOEFL">TOEFL</a>(2010年5月)</h3>
<p>大学院の入試で、英語の試験の代わりに<a class="keyword" href="https://d.hatena.ne.jp/keyword/TOEFL">TOEFL</a> iBTのスコアを提出する必要があったので受けた。<br/>
これは手元に記録がある。
120点満点で、Reading 27, Listening 22, Speaking 14, Writing 20で83点。
Reading > Listening > Writing > Speaking という大小関係なのは納得である。Speakingは普段全然やってないから、できる気がしないからな。</p>
<h3 id="TOEIC2011年11月"><a class="keyword" href="https://d.hatena.ne.jp/keyword/TOEIC">TOEIC</a>(2011年11月)</h3>
<p>M1の11月なので、就活のためにもう一度受けとくかと思って受けたんだろう。
これは手元に記録がある。総合975(Listening 495, Reading 480)。
絶対リーディングのほうが自信があったのに、リスニングが満点でリーディングが満点-15というのが意外。</p>
<h2 id="社会人">社会人</h2>
<h3 id="TOEIC-2013年4月"><a class="keyword" href="https://d.hatena.ne.jp/keyword/TOEIC">TOEIC</a> (2013年4月)</h3>
<p>新卒で入った会社で、業務後に受けさせられたやつ。なので団体試験。(<a class="keyword" href="https://d.hatena.ne.jp/keyword/TOEIC">TOEIC</a> IPテスト)
確か905点。</p>
<h3 id="Anki">Anki</h3>
<p>単語帳アプリ。出題と復習までの間隔をうまく調整してくれる。PCと<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>で同期が取れる。そういう特徴についてはここで説明する気はないので他を見てほしいが、オススメのアプリである。<br/>
Ankiに入れた単語帳は英語だけじゃなくて、資格試験(応用情報/<a class="keyword" href="https://d.hatena.ne.jp/keyword/LPIC">LPIC</a>/セキュスペ)で覚えたいものとか、その他IT関連で覚えておきたいものを適宜入れていた。前職では社員食堂があったので、そこで並ぶときか昼飯を食べながらでAnkiをやることが多かった。<br/>
ただ、何年かログインしていないとデータが消える。最近(2023年12月)にAnkiを再度使おうと思って、ログインしたら消えていた。</p>
<p>Ankiを使う場合、自分で問題を作るか、既存の(公開されている)デッキを使うかのどちらかになる。
資格試験の途中などで、覚えたいものが出てきた場合は当然前者だが、ここで大きな欠点がある。自分で問題を作って入力するのがめちゃめちゃ時間がかかるのだ。
休日にカードを作り始めたら1〜2時間経過していたことも結構あったような覚えがある。</p>
<p>単語のリストがあって(たとえばSVLとか)、1000個の単語とその訳を覚えたい、とかであればある程度自動的にできるかもしれない。……が、俺は普段、覚えたい単語に出会ったときは以下のステップを踏む。</p>
<ul>
<li>ネットの<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B1%D1%BC%AD%CF%BA">英辞郎</a>を引く</li>
<li>電子辞書の例文一覧で単語を検索する</li>
<li>2つの中から良さそうな例文を選ぶ</li>
<li>単語帳に入力する</li>
</ul>
<p>なので時間もかかるし自動化もし辛い。悩ましいところである。</p>
<p>語彙力高めの日-英のデッキは少ないので、
SATとか<a class="keyword" href="https://d.hatena.ne.jp/keyword/GRE">GRE</a>向けの、英英の(日本語訳の無い)デッキを使ってた。
……という話が旧ブログに書いてあるな。</p>
<p><a href="http://luvtome.blog5.fc2.com/blog-entry-593.html">http://luvtome.blog5.fc2.com/blog-entry-593.html</a><br/>
<a href="http://luvtome.blog5.fc2.com/blog-entry-600.html">http://luvtome.blog5.fc2.com/blog-entry-600.html</a><br/>
<a href="http://luvtome.blog5.fc2.com/blog-entry-613.html">http://luvtome.blog5.fc2.com/blog-entry-613.html</a></p>
<h3 id="TestYourVocab">TestYourVocab</h3>
<p><figure class="figure-image figure-image-fotolife" title="2023年12月23日の結果"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20231223/20231223223204.png" width="1145" height="494" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>2023年12月23日の結果</figcaption></figure></p>
<p>(2023年12月23日時点)
書くついでにまた測ったら9201と言われた。
10000まで行きたい〜と思いつつ、あと800覚えるのなかなか大変だなぁ。うへ。</p>
<h3 id="英字新聞">英字新聞</h3>
<p>ProPublicaの<a class="keyword" href="https://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウントをフォローしている。何のきっかけで知ったのか忘れたけど。
ProPublica、<a class="keyword" href="https://d.hatena.ne.jp/keyword/New%20York%20Times">New York Times</a>はたまに読んでた。……久々に<a class="keyword" href="https://d.hatena.ne.jp/keyword/New%20York%20Times">New York Times</a>を再訪問したら、有料会員にならないと全然記事が読めなくなっていてガッカリした。
最近はGuardianが無料で全部読めるということに気づいたので、たまに読んでいる。</p>
<hr />
<p>何か書き加えることができたら加筆します。<br/>
それでは。</p>
soratokimitonoaidani
IIJmioの料金プランをギガプランに変更した
hatenablog://entry/820878482960090506
2023-08-20T17:42:09+09:00
2023-08-20T17:42:09+09:00 IIJmioの料金プランを2023年6月18日に、昔のライトスタートプラン(データ6GB)→新しいギガプラン(データ5GB)に変更したという話。 請求額は税込み2700円〜3000円から1000円程度に減った。もっと早くに変えておけばよかったぜ……! プラン変更前の状況 マイページから確認すると下記のとおりだった。 申し込み日:2016年10月30日 料金プラン:ライトスタートプラン 毎月の料金は、 月額基本料(ライトスタートプラン) 税抜1520円、税込1672円 音声通話機能付帯料 税抜700円、税込770円 で合計税込2442円。 これに通話代が数百円かかって、月に2700円〜3000円…
<p><a class="keyword" href="https://d.hatena.ne.jp/keyword/IIJmio">IIJmio</a>の料金プランを2023年6月18日に、昔のライトスタートプラン(データ6GB)→新しいギガプラン(データ5GB)に変更したという話。<br/>
請求額は税込み2700円〜3000円から1000円程度に減った。もっと早くに変えておけばよかったぜ……!</p>
<h2 id="プラン変更前の状況">プラン変更前の状況</h2>
<p>マイページから確認すると下記のとおりだった。</p>
<p>申し込み日:2016年10月30日<br/>
料金プラン:ライトスタートプラン</p>
<p>毎月の料金は、<br/>
月額基本料(ライトスタートプラン) 税抜1520円、税込1672円<br/>
音声通話機能付帯料 税抜700円、税込770円<br/>
で合計税込2442円。<br/>
これに通話代が数百円かかって、月に2700円〜3000円くらい払っている。</p>
<p>倉田けい さんの<a class="keyword" href="https://d.hatena.ne.jp/keyword/IIJmio">IIJmio</a>の広告が<a class="keyword" href="https://d.hatena.ne.jp/keyword/Twitter">Twitter</a>で流れてきて、俺は重い腰を上げたのであった。</p>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">🌸<a href="https://twitter.com/hashtag/%E3%82%AE%E3%82%AC%E3%83%97%E3%83%A9%E3%83%B3?src=hash&ref_src=twsrc%5Etfw">#ギガプラン</a> ×<a class="keyword" href="https://d.hatena.ne.jp/keyword/SNS">SNS</a>マンガ家コラボ🌸<br>第4弾は…倉田けい(<a href="https://twitter.com/kurata_kei?ref_src=twsrc%5Etfw">@kurata_kei</a>)さん✨<br><br>池に<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>を落としたら女神が現れた⁉️<br>しかし見せられたのは金や銀の斧ではなく…🧐<br><br>価格はそのままでギガ増量😍<br>4ギガ→5ギガになっても990円(税込)<a href="https://twitter.com/hashtag/IIJmio?src=hash&ref_src=twsrc%5Etfw">#IIJmio</a> で通信費をお得に👏<br><br>詳細はこちら<a href="https://t.co/iLsd7HaTVj">https://t.co/iLsd7HaTVj</a> <a href="https://t.co/fsYkWcEjp6">pic.twitter.com/fsYkWcEjp6</a></p>— <a class="keyword" href="https://d.hatena.ne.jp/keyword/IIJmio">IIJmio</a> (@<a class="keyword" href="https://d.hatena.ne.jp/keyword/iijmio">iijmio</a>) <a href="https://twitter.com/iijmio/status/1655875258157764608?ref_src=twsrc%5Etfw">May 9, 2023</a></blockquote>
<p> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p>
<h2 id="変更先のギガプランを決める">変更先のギガプランを決める</h2>
<p>ライトスタートプランは、データが毎月6GB使えるプランである。<br/>
<a href="https://www.itmedia.co.jp/mobile/articles/2302/22/news203.html">https://www.itmedia.co.jp/mobile/articles/2302/22/news203.html</a> によれば、
4GBのプランが2023年2月に5GBに増量された。
ライトスタートプランの6GBから移行するなら、これが良いだろう。</p>
<p>過去30日間のデータ利用量を確認したら(正直ここはもっと前までデータ利用量を確認させてほしい)、ちょうど6GBちょっとだった。<br/>
ただこれは1泊旅行に行ったときに2GB以上使っている影響が大きい。普段は4GBでギリギリ、5GBなら余裕を持って使える、というところか。5GBに上がってくれて助かった。</p>
<p>と思ったらどうやらギガプランの場合は月ごとのデータ利用量を照会できるらしい。<br/>
<a href="https://help.iijmio.jp/answer/611e5819ae05cd001c0ec994?search=true">https://help.iijmio.jp/answer/611e5819ae05cd001c0ec994?search=true</a><br/>
プラン切替後に確認したが、 <strong>ギガプランを使っている時期だけでなく旧プランのときも含めて</strong> 過去1年分の月ごとのデータ利用量を確認できる。</p>
<p>(余談:<a class="keyword" href="https://d.hatena.ne.jp/keyword/itmedia">itmedia</a>の記事中の資料によればギガプランの人が9割近くいるらしい。俺完全にラガードじゃん。)</p>
<h2 id="プランのデータを分け合う方式の違い">プランの「データを分け合う方式」の違い</h2>
<p><a href="https://www.iijmio.jp/hdc/spec/index.html#comparison">https://www.iijmio.jp/hdc/spec/index.html#comparison</a> の比較にある通りで、データを分け合う方式が異なる。</p>
<blockquote><p>新しいギガプラン = プラン”間”でデータを分け合う<br/>
例)2ギガプラン、5ギガプランをそれぞれ契約。合計7ギガを2人で分け合う。<br/>
従来のライトスタートプランなど = プラン”内”でデータを分け合う<br/>
例)ファミリーシェアプラン(12GB)内で<a class="keyword" href="https://d.hatena.ne.jp/keyword/SIM%A5%AB%A1%BC%A5%C9">SIMカード</a>3枚でデータ量を分け合う。<br/>
<a href="https://www.iijmio.jp/hdc/spec/index.html#comparison">https://www.iijmio.jp/hdc/spec/index.html#comparison</a></p></blockquote>
<p>俺の<a class="keyword" href="https://d.hatena.ne.jp/keyword/iPad">iPad</a> Proは、SIMを差せるのに差さずに使い続けるという変な使い方をしている。<br/>
ギガプランの場合、もし<a class="keyword" href="https://d.hatena.ne.jp/keyword/iPad">iPad</a>にSIMを入れたくなったら、新しく別のギガプランを契約する必要がある。SIMが2枚必要ならば契約プランも2つ必要だからだ。<br/>
この点がずっと引っかかっていて躊躇っていたけど、いまはSIM無しで使っているので、SIMを入れたくなったら考えることにしよう……。</p>
<h2 id="プラン変更時の注意点">プラン変更時の注意点</h2>
<p>重要説明事項からコピー。</p>
<blockquote><p>・<a class="keyword" href="https://d.hatena.ne.jp/keyword/IIJmio">IIJmio</a>モバイルサービス(ギガプラン)へ変更された場合、元のプラン(<a class="keyword" href="https://d.hatena.ne.jp/keyword/IIJmio">IIJmio</a>モバイルサービスまたは<a class="keyword" href="https://d.hatena.ne.jp/keyword/IIJmio">IIJmio</a>モバイルプラスサービス)へは戻すことはできません。<br/>
・<a class="keyword" href="https://d.hatena.ne.jp/keyword/IIJmio">IIJmio</a>モバイルサービスまたは<a class="keyword" href="https://d.hatena.ne.jp/keyword/IIJmio">IIJmio</a>モバイルプラスサービスでご利用中のクーポン残量を引き継ぐことはできません。残量は消滅します。</p></blockquote>
<p>ずっと溜まっていたデータ通信量の残量は消えてしまうので注意。</p>
<h2 id="プラン変更後の状況">プラン変更後の状況</h2>
<p>6月中旬に変更したので、7月1日から適用になった。</p>
<p>データについて。上記の通り、変更のタイミングでクーポン残量が無くなったが、7月は5GBのうち4.7GBを使った。この調子なら少しずつ溜まるので大丈夫だろう。</p>
<p>料金について。
まずギガプランの5GBは税抜900円、税込990円だ。<br/>
2023年7月利用分の請求金額には、6月の電話の通話料が入る。(電話の通話料に関しては1ヶ月ズレるらしい)6月はたまたま電話を使わなかったので、合計の支払い料は1000円を切った。
マジか……ネットで完結する手続きするだけで月間1700円くらい浮いたぞ……もっと早くに変えておけばよかったぜ……!</p>
<p>それでは。</p>
soratokimitonoaidani
daskのquery関数で変数名を指定する方法
hatenablog://entry/4207112889967395666
2023-02-28T23:58:43+09:00
2023-03-01T01:36:30+09:00 daskでデータ絞り込みをするためにquery関数を使ったけど、構文が難しくてちょっと詰まった話。 daskのDataFrameに対するquery関数の公式ドキュメントはこちらだ。 dask.dataframe.DataFrame.query このドキュメントを見ると、 「pandasは@で変数名を使えるが、daskではそれは使えないので、代わりにf文字列かlocal_dictキーワードを使ってくれ」と書いてある。 なるほど、@の代わりにf文字列を使えばそれで良いのね。……と単純に考えていると、ちょっとつまずく。という話である。 準備 サンプルデータの作成 数値型のカラムの場合 文字列型のカラ…
<p>daskでデータ絞り込みをするためにquery関数を使ったけど、構文が難しくてちょっと詰まった話。</p>
<p>daskのDataFrameに対するquery関数の公式ドキュメントはこちらだ。<br/>
<a href="https://docs.dask.org/en/stable/generated/dask.dataframe.DataFrame.query.html">dask.dataframe.DataFrame.query</a></p>
<p>このドキュメントを見ると、<br/>
「pandasは@で変数名を使えるが、daskではそれは使えないので、代わりにf文字列かlocal_dictキーワードを使ってくれ」と書いてある。<br/>
なるほど、@の代わりにf文字列を使えばそれで良いのね。……と単純に考えていると、ちょっとつまずく。という話である。</p>
<ul class="table-of-contents">
<li><a href="#準備">準備</a></li>
<li><a href="#サンプルデータの作成">サンプルデータの作成</a></li>
<li><a href="#数値型のカラムの場合">数値型のカラムの場合</a></li>
<li><a href="#文字列型のカラムの場合">文字列型のカラムの場合</a></li>
<li><a href="#数字が入っている文字列型の場合">数字が入っている文字列型の場合</a></li>
<li><a href="#まとめ">まとめ</a></li>
</ul>
<h2 id="準備">準備</h2>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd
<span class="synPreProc">import</span> dask.dataframe <span class="synStatement">as</span> dd
<span class="synPreProc">import</span> dask
pd.options.display.notebook_repr_html = <span class="synIdentifier">False</span> <span class="synComment"># jupyter notebook上での出力形式を制御するために書いています。無くても動きます。</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 動作環境の確認</span>
<span class="synIdentifier">print</span>(pd.__version__)
<span class="synIdentifier">print</span>(dask.__version__)
<span class="synComment"># --------------------</span>
<span class="synConstant">1.1</span>.<span class="synConstant">2</span>
<span class="synConstant">2023.1</span>.<span class="synConstant">0</span>
</pre>
<h2 id="サンプルデータの作成">サンプルデータの作成</h2>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># データに特に意味はない。https://linus-mk.hatenablog.com/entry/pandas-unique-integer-id から持ってきて適宜改変。</span>
df = pd.DataFrame({
<span class="synConstant">'name'</span> : [<span class="synConstant">'Alice'</span>, <span class="synConstant">'Bob'</span>, <span class="synConstant">'Charlie'</span>, <span class="synConstant">'Charlie'</span>, <span class="synConstant">'Alice'</span>, <span class="synConstant">'Bob'</span>],
<span class="synConstant">'item'</span> : [<span class="synConstant">'aaa'</span>, <span class="synConstant">'bbb'</span>, <span class="synConstant">'ccc'</span>, <span class="synConstant">'ddd'</span>, <span class="synConstant">'eee'</span>, <span class="synConstant">'fff'</span>],
<span class="synConstant">'number'</span> : [<span class="synConstant">3</span>, <span class="synConstant">2</span>, <span class="synConstant">4</span>, <span class="synConstant">3</span>, <span class="synConstant">2</span>, <span class="synConstant">1</span>],
<span class="synConstant">'id_code'</span> : [<span class="synConstant">'012'</span>, <span class="synConstant">'123'</span>, <span class="synConstant">'234'</span>, <span class="synConstant">'123'</span>, <span class="synConstant">'012'</span>, <span class="synConstant">'345'</span>]
})
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">0</span> Alice aaa <span class="synConstant">3</span> <span class="synConstant">012</span>
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">2</span> Charlie ccc <span class="synConstant">4</span> <span class="synConstant">234</span>
<span class="synConstant">3</span> Charlie ddd <span class="synConstant">3</span> <span class="synConstant">123</span>
<span class="synConstant">4</span> Alice eee <span class="synConstant">2</span> <span class="synConstant">012</span>
<span class="synConstant">5</span> Bob fff <span class="synConstant">1</span> <span class="synConstant">345</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df.dtypes
<span class="synComment"># --------------------</span>
name <span class="synIdentifier">object</span>
item <span class="synIdentifier">object</span>
number int64
id_code <span class="synIdentifier">object</span>
dtype: <span class="synIdentifier">object</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>ddf = dd.from_pandas(df)
<span class="synComment"># --------------------</span>
---------------------------------------------------------------------------
<span class="synType">ValueError</span> Traceback (most recent call last)
<ipython-<span class="synIdentifier">input</span>-<span class="synConstant">6</span>-bcb6b963da62> <span class="synStatement">in</span> <module>
----> <span class="synConstant">1</span> ddf = dd.from_pandas(df)
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/dask/dataframe/io/io.py <span class="synStatement">in</span> from_pandas(data, npartitions, chunksize, sort, name)
<span class="synConstant">260</span>
<span class="synConstant">261</span> <span class="synStatement">if</span> (npartitions <span class="synStatement">is</span> <span class="synIdentifier">None</span>) == (chunksize <span class="synStatement">is</span> <span class="synIdentifier">None</span>):
--> <span class="synConstant">262</span> <span class="synStatement">raise</span> <span class="synType">ValueError</span>(<span class="synConstant">"Exactly one of npartitions and chunksize must be specified."</span>)
<span class="synConstant">263</span>
<span class="synConstant">264</span> nrows = <span class="synIdentifier">len</span>(data)
<span class="synType">ValueError</span>: Exactly one of npartitions <span class="synStatement">and</span> chunksize must be specified.
</pre>
<p>どうもよく分かっていないのだが、dask.dataframe.from_pandasはnpartitionsとchunksizeのうちどちらか片方(のみ)を指定する必要があるらしい。
今は特に何でも良いので、npartitions=1を指定する。</p>
<pre class="code lang-python" data-lang="python" data-unlink>ddf = dd.from_pandas(df, npartitions=<span class="synConstant">1</span>)
<span class="synIdentifier">print</span>(ddf)
<span class="synComment"># --------------------</span>
Dask DataFrame Structure:
name item number id_code
npartitions=<span class="synConstant">1</span>
<span class="synConstant">0</span> <span class="synIdentifier">object</span> <span class="synIdentifier">object</span> int64 <span class="synIdentifier">object</span>
<span class="synConstant">5</span> ... ... ... ...
Dask Name: from_pandas, <span class="synConstant">1</span> graph layer
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>ddf.compute()
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">0</span> Alice aaa <span class="synConstant">3</span> <span class="synConstant">012</span>
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">2</span> Charlie ccc <span class="synConstant">4</span> <span class="synConstant">234</span>
<span class="synConstant">3</span> Charlie ddd <span class="synConstant">3</span> <span class="synConstant">123</span>
<span class="synConstant">4</span> Alice eee <span class="synConstant">2</span> <span class="synConstant">012</span>
<span class="synConstant">5</span> Bob fff <span class="synConstant">1</span> <span class="synConstant">345</span>
</pre>
<p>これで準備はできた。</p>
<h2 id="数値型のカラムの場合">数値型のカラムの場合</h2>
<p><a href="https://docs.dask.org/en/stable/generated/dask.dataframe.DataFrame.query.html">上述の公式ドキュメント</a>にも載っている、数字の例を見てみよう。<br/>
まず、データのうち、numberカラムが2であるものを抽出しよう。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># pandas 直接値を指定</span>
df.query(<span class="synConstant">"number==2"</span>)
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">4</span> Alice eee <span class="synConstant">2</span> <span class="synConstant">012</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># dask 直接値を指定</span>
ddf.query(<span class="synConstant">"number==2"</span>).compute()
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">4</span> Alice eee <span class="synConstant">2</span> <span class="synConstant">012</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># pandas 変数名を使用 @</span>
num = <span class="synConstant">2</span>
df.query(f<span class="synConstant">"number==@num"</span>)
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">4</span> Alice eee <span class="synConstant">2</span> <span class="synConstant">012</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># dask 変数名を使用 f文字列、成功</span>
num = <span class="synConstant">2</span>
ddf.query(f<span class="synConstant">"number=={num}"</span>).compute()
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">4</span> Alice eee <span class="synConstant">2</span> <span class="synConstant">012</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># pandas 変数名を使用 実はf文字列でも行ける</span>
num = <span class="synConstant">2</span>
df.query(f<span class="synConstant">"number=={num}"</span>)
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">4</span> Alice eee <span class="synConstant">2</span> <span class="synConstant">012</span>
</pre>
<p>pandas側で<code>@variable_name</code>と書く代わりに、daskでは<code>{variable_name}</code>と書けば良さそうな気がしてくる。
ところがそれが上手く行かないケースが存在するのだ。</p>
<h2 id="文字列型のカラムの場合">文字列型のカラムの場合</h2>
<p>データのうち、nameカラムが"Bob"であるものを抽出しよう。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># pandas 直接値を指定</span>
df.query(<span class="synConstant">"name=='Bob'"</span>)
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">5</span> Bob fff <span class="synConstant">1</span> <span class="synConstant">345</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># dask 直接値を指定</span>
ddf.query(<span class="synConstant">"name=='Bob'"</span>).compute()
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">5</span> Bob fff <span class="synConstant">1</span> <span class="synConstant">345</span>
</pre>
<p>ここまでは何も問題ない。<br/>
ところが、変数名を使用すると状況が変わってくる。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># pandas 変数名を使用 @</span>
target = <span class="synConstant">'Bob'</span>
df.query(f<span class="synConstant">"name==@target"</span>)
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">5</span> Bob fff <span class="synConstant">1</span> <span class="synConstant">345</span>
</pre>
<p>pandas側で<code>@variable_name</code>と書く代わりに、daskでは<code>{variable_name}</code>と書くと失敗する。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># dask 変数名を使用 f文字列 失敗例</span>
target = <span class="synConstant">'Bob'</span>
ddf.query(f<span class="synConstant">"name=={target}"</span>).compute()
<span class="synComment"># --------------------</span>
エラー。長いので折りたたみます。
</pre>
<p><details><summary>クリックでエラー内容を表示</summary><div></p>
<pre class="code" data-lang="" data-unlink> KeyError Traceback (most recent call last)
/usr/local/lib/python3.8/site-packages/pandas/core/computation/scope.py in resolve(self, key, is_local)
187 if self.has_resolvers:
--> 188 return self.resolvers[key]
189
/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/collections/__init__.py in __getitem__(self, key)
897 pass
--> 898 return self.__missing__(key) # support subclasses that define __missing__
899
/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/collections/__init__.py in __missing__(self, key)
889 def __missing__(self, key):
--> 890 raise KeyError(key)
891
KeyError: 'Bob'
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
/usr/local/lib/python3.8/site-packages/pandas/core/computation/scope.py in resolve(self, key, is_local)
198 # e.g., df[df > 0]
--> 199 return self.temps[key]
200 except KeyError as err:
KeyError: 'Bob'
The above exception was the direct cause of the following exception:
UndefinedVariableError Traceback (most recent call last)
/usr/local/lib/python3.8/site-packages/dask/dataframe/utils.py in raise_on_meta_error(funcname, udf)
194 try:
--> 195 yield
196 except Exception as e:
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in _emulate(func, udf, *args, **kwargs)
6570 with raise_on_meta_error(funcname(func), udf=udf), check_numeric_only_deprecation():
-> 6571 return func(*_extract_meta(args, True), **_extract_meta(kwargs, True))
6572
/usr/local/lib/python3.8/site-packages/dask/utils.py in __call__(self, _methodcaller__obj, *args, **kwargs)
1102 def __call__(self, __obj, *args, **kwargs):
-> 1103 return getattr(__obj, self.method)(*args, **kwargs)
1104
/usr/local/lib/python3.8/site-packages/pandas/core/frame.py in query(self, expr, inplace, **kwargs)
3339 kwargs["target"] = None
-> 3340 res = self.eval(expr, **kwargs)
3341
/usr/local/lib/python3.8/site-packages/pandas/core/frame.py in eval(self, expr, inplace, **kwargs)
3469
-> 3470 return _eval(expr, inplace=inplace, **kwargs)
3471
/usr/local/lib/python3.8/site-packages/pandas/core/computation/eval.py in eval(expr, parser, engine, truediv, local_dict, global_dict, resolvers, level, target, inplace)
340
--> 341 parsed_expr = Expr(expr, engine=engine, parser=parser, env=env)
342
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in __init__(self, expr, engine, parser, env, level)
786 self._visitor = _parsers[parser](self.env, self.engine, self.parser)
--> 787 self.terms = self.parse()
788
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in parse(self)
805 """
--> 806 return self._visitor.visit(self.expr)
807
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
397 visitor = getattr(self, method)
--> 398 return visitor(node, **kwargs)
399
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit_Module(self, node, **kwargs)
403 expr = node.body[0]
--> 404 return self.visit(expr, **kwargs)
405
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
397 visitor = getattr(self, method)
--> 398 return visitor(node, **kwargs)
399
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit_Expr(self, node, **kwargs)
406 def visit_Expr(self, node, **kwargs):
--> 407 return self.visit(node.value, **kwargs)
408
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
397 visitor = getattr(self, method)
--> 398 return visitor(node, **kwargs)
399
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit_Compare(self, node, **kwargs)
698 binop = ast.BinOp(op=op, left=node.left, right=comps[0])
--> 699 return self.visit(binop)
700
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
397 visitor = getattr(self, method)
--> 398 return visitor(node, **kwargs)
399
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit_BinOp(self, node, **kwargs)
519 def visit_BinOp(self, node, **kwargs):
--> 520 op, op_class, left, right = self._maybe_transform_eq_ne(node)
521 left, right = self._maybe_downcast_constants(left, right)
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in _maybe_transform_eq_ne(self, node, left, right)
440 if right is None:
--> 441 right = self.visit(node.right, side="right")
442 op, op_class, left, right = self._rewrite_membership_op(node, left, right)
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
397 visitor = getattr(self, method)
--> 398 return visitor(node, **kwargs)
399
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit_Name(self, node, **kwargs)
532 def visit_Name(self, node, **kwargs):
--> 533 return self.term_type(node.id, self.env, **kwargs)
534
/usr/local/lib/python3.8/site-packages/pandas/core/computation/ops.py in __init__(self, name, env, side, encoding)
83 self.is_local = tname.startswith(_LOCAL_TAG) or tname in _DEFAULT_GLOBALS
---> 84 self._value = self._resolve_name()
85 self.encoding = encoding
/usr/local/lib/python3.8/site-packages/pandas/core/computation/ops.py in _resolve_name(self)
100 def _resolve_name(self):
--> 101 res = self.env.resolve(self.local_name, is_local=self.is_local)
102 self.update(res)
/usr/local/lib/python3.8/site-packages/pandas/core/computation/scope.py in resolve(self, key, is_local)
203
--> 204 raise UndefinedVariableError(key, is_local) from err
205
UndefinedVariableError: name 'Bob' is not defined
The above exception was the direct cause of the following exception:
ValueError Traceback (most recent call last)
<ipython-input-17-6b73727f207c> in <module>
1 # dask 変数名を使用 f文字列 失敗例
2 target = 'Bob'
----> 3 ddf.query(f"name=={target}").compute()
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in query(self, expr, **kwargs)
5178 2 1 3 2
5179 """
-> 5180 return self.map_partitions(M.query, expr, **kwargs)
5181
5182 @derived_from(pd.DataFrame)
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in map_partitions(self, func, *args, **kwargs)
873 None as the division.
874 """
--> 875 return map_partitions(func, self, *args, **kwargs)
876
877 @insert_meta_param_description(pad=12)
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in map_partitions(func, meta, enforce_metadata, transform_divisions, align_dataframes, *args, **kwargs)
6639 dfs = [df for df in args if isinstance(df, _Frame)]
6640
-> 6641 meta = _get_meta_map_partitions(args, dfs, func, kwargs, meta, parent_meta)
6642 if all(isinstance(arg, Scalar) for arg in args):
6643 layer = {
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in _get_meta_map_partitions(args, dfs, func, kwargs, meta, parent_meta)
6750 # Use non-normalized kwargs here, as we want the real values (not
6751 # delayed values)
-> 6752 meta = _emulate(func, *args, udf=True, **kwargs)
6753 meta_is_emulated = True
6754 else:
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in _emulate(func, udf, *args, **kwargs)
6569 """
6570 with raise_on_meta_error(funcname(func), udf=udf), check_numeric_only_deprecation():
-> 6571 return func(*_extract_meta(args, True), **_extract_meta(kwargs, True))
6572
6573
/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/contextlib.py in __exit__(self, type, value, traceback)
129 value = type()
130 try:
--> 131 self.gen.throw(type, value, traceback)
132 except StopIteration as exc:
133 # Suppress StopIteration *unless* it's the same exception that
/usr/local/lib/python3.8/site-packages/dask/dataframe/utils.py in raise_on_meta_error(funcname, udf)
214 )
215 msg = msg.format(f" in `{funcname}`" if funcname else "", repr(e), tb)
--> 216 raise ValueError(msg) from e
217
218
ValueError: Metadata inference failed in `query`.
You have supplied a custom function and Dask is unable to
determine the type of output that that function returns.
To resolve this please provide a meta= keyword.
The docstring of the Dask function you ran should have more information.
Original error is below:
------------------------
UndefinedVariableError("name 'Bob' is not defined")
Traceback:
---------
File "/usr/local/lib/python3.8/site-packages/dask/dataframe/utils.py", line 195, in raise_on_meta_error
yield
File "/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py", line 6571, in _emulate
return func(*_extract_meta(args, True), **_extract_meta(kwargs, True))
File "/usr/local/lib/python3.8/site-packages/dask/utils.py", line 1103, in __call__
return getattr(__obj, self.method)(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/frame.py", line 3340, in query
res = self.eval(expr, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/frame.py", line 3470, in eval
return _eval(expr, inplace=inplace, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/eval.py", line 341, in eval
parsed_expr = Expr(expr, engine=engine, parser=parser, env=env)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 787, in __init__
self.terms = self.parse()
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 806, in parse
return self._visitor.visit(self.expr)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 398, in visit
return visitor(node, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 404, in visit_Module
return self.visit(expr, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 398, in visit
return visitor(node, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 407, in visit_Expr
return self.visit(node.value, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 398, in visit
return visitor(node, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 699, in visit_Compare
return self.visit(binop)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 398, in visit
return visitor(node, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 520, in visit_BinOp
op, op_class, left, right = self._maybe_transform_eq_ne(node)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 441, in _maybe_transform_eq_ne
right = self.visit(node.right, side="right")
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 398, in visit
return visitor(node, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 533, in visit_Name
return self.term_type(node.id, self.env, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/ops.py", line 84, in __init__
self._value = self._resolve_name()
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/ops.py", line 101, in _resolve_name
res = self.env.resolve(self.local_name, is_local=self.is_local)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/scope.py", line 204, in resolve
raise UndefinedVariableError(key, is_local) from err</pre>
<p></div></details></p>
<p>またpandasでも似たようなエラーが出る。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># pandas 変数名を使用 f文字列 失敗例</span>
target = <span class="synConstant">'Bob'</span>
df.query(f<span class="synConstant">"name=={target}"</span>)
<span class="synComment"># --------------------</span>
エラー。長いので折りたたみます。
</pre>
<p><details><summary>クリックでエラー内容を表示</summary><div></p>
<pre class="code" data-lang="" data-unlink> KeyError Traceback (most recent call last)
/usr/local/lib/python3.8/site-packages/pandas/core/computation/scope.py in resolve(self, key, is_local)
187 if self.has_resolvers:
--> 188 return self.resolvers[key]
189
/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/collections/__init__.py in __getitem__(self, key)
897 pass
--> 898 return self.__missing__(key) # support subclasses that define __missing__
899
/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/collections/__init__.py in __missing__(self, key)
889 def __missing__(self, key):
--> 890 raise KeyError(key)
891
KeyError: 'Bob'
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
/usr/local/lib/python3.8/site-packages/pandas/core/computation/scope.py in resolve(self, key, is_local)
198 # e.g., df[df > 0]
--> 199 return self.temps[key]
200 except KeyError as err:
KeyError: 'Bob'
The above exception was the direct cause of the following exception:
UndefinedVariableError Traceback (most recent call last)
<ipython-input-18-52c23030a7f6> in <module>
1 # pandas 変数名を使用 f文字列 失敗例
2 target = 'Bob'
----> 3 df.query(f"name=={target}")
/usr/local/lib/python3.8/site-packages/pandas/core/frame.py in query(self, expr, inplace, **kwargs)
3338 kwargs["level"] = kwargs.pop("level", 0) + 1
3339 kwargs["target"] = None
-> 3340 res = self.eval(expr, **kwargs)
3341
3342 try:
/usr/local/lib/python3.8/site-packages/pandas/core/frame.py in eval(self, expr, inplace, **kwargs)
3468 kwargs["resolvers"] = kwargs.get("resolvers", ()) + tuple(resolvers)
3469
-> 3470 return _eval(expr, inplace=inplace, **kwargs)
3471
3472 def select_dtypes(self, include=None, exclude=None) -> "DataFrame":
/usr/local/lib/python3.8/site-packages/pandas/core/computation/eval.py in eval(expr, parser, engine, truediv, local_dict, global_dict, resolvers, level, target, inplace)
339 )
340
--> 341 parsed_expr = Expr(expr, engine=engine, parser=parser, env=env)
342
343 # construct the engine and evaluate the parsed expression
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in __init__(self, expr, engine, parser, env, level)
785 self.parser = parser
786 self._visitor = _parsers[parser](self.env, self.engine, self.parser)
--> 787 self.terms = self.parse()
788
789 @property
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in parse(self)
804 Parse an expression.
805 """
--> 806 return self._visitor.visit(self.expr)
807
808 @property
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
396 method = "visit_" + type(node).__name__
397 visitor = getattr(self, method)
--> 398 return visitor(node, **kwargs)
399
400 def visit_Module(self, node, **kwargs):
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit_Module(self, node, **kwargs)
402 raise SyntaxError("only a single expression is allowed")
403 expr = node.body[0]
--> 404 return self.visit(expr, **kwargs)
405
406 def visit_Expr(self, node, **kwargs):
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
396 method = "visit_" + type(node).__name__
397 visitor = getattr(self, method)
--> 398 return visitor(node, **kwargs)
399
400 def visit_Module(self, node, **kwargs):
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit_Expr(self, node, **kwargs)
405
406 def visit_Expr(self, node, **kwargs):
--> 407 return self.visit(node.value, **kwargs)
408
409 def _rewrite_membership_op(self, node, left, right):
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
396 method = "visit_" + type(node).__name__
397 visitor = getattr(self, method)
--> 398 return visitor(node, **kwargs)
399
400 def visit_Module(self, node, **kwargs):
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit_Compare(self, node, **kwargs)
697 op = self.translate_In(ops[0])
698 binop = ast.BinOp(op=op, left=node.left, right=comps[0])
--> 699 return self.visit(binop)
700
701 # recursive case: we have a chained comparison, a CMP b CMP c, etc.
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
396 method = "visit_" + type(node).__name__
397 visitor = getattr(self, method)
--> 398 return visitor(node, **kwargs)
399
400 def visit_Module(self, node, **kwargs):
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit_BinOp(self, node, **kwargs)
518
519 def visit_BinOp(self, node, **kwargs):
--> 520 op, op_class, left, right = self._maybe_transform_eq_ne(node)
521 left, right = self._maybe_downcast_constants(left, right)
522 return self._maybe_evaluate_binop(op, op_class, left, right)
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in _maybe_transform_eq_ne(self, node, left, right)
439 left = self.visit(node.left, side="left")
440 if right is None:
--> 441 right = self.visit(node.right, side="right")
442 op, op_class, left, right = self._rewrite_membership_op(node, left, right)
443 return op, op_class, left, right
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
396 method = "visit_" + type(node).__name__
397 visitor = getattr(self, method)
--> 398 return visitor(node, **kwargs)
399
400 def visit_Module(self, node, **kwargs):
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit_Name(self, node, **kwargs)
531
532 def visit_Name(self, node, **kwargs):
--> 533 return self.term_type(node.id, self.env, **kwargs)
534
535 def visit_NameConstant(self, node, **kwargs):
/usr/local/lib/python3.8/site-packages/pandas/core/computation/ops.py in __init__(self, name, env, side, encoding)
82 tname = str(name)
83 self.is_local = tname.startswith(_LOCAL_TAG) or tname in _DEFAULT_GLOBALS
---> 84 self._value = self._resolve_name()
85 self.encoding = encoding
86
/usr/local/lib/python3.8/site-packages/pandas/core/computation/ops.py in _resolve_name(self)
99
100 def _resolve_name(self):
--> 101 res = self.env.resolve(self.local_name, is_local=self.is_local)
102 self.update(res)
103
/usr/local/lib/python3.8/site-packages/pandas/core/computation/scope.py in resolve(self, key, is_local)
202 from pandas.core.computation.ops import UndefinedVariableError
203
--> 204 raise UndefinedVariableError(key, is_local) from err
205
206 def swapkey(self, old_key: str, new_key: str, new_value=None):
UndefinedVariableError: name 'Bob' is not defined</pre>
<p></div></details></p>
<p>これはquery関数の中にある文字列を単独で表示させるとよく分かる。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">print</span>(f<span class="synConstant">"name=={target}"</span>)
<span class="synComment"># --------------------</span>
name==Bob
</pre>
<p>Bobに引用符をつけなければいけないのに、ついていない。これではBobはただの列名として扱われるはずだ。<br/>
正しい結果を得るためには、f文字列の中、Bobの外側に引用符を書く必要がある。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># dask 変数名を使用 f文字列 成功例</span>
target = <span class="synConstant">'Bob'</span>
ddf.query(f<span class="synConstant">"name=='{target}'"</span>).compute()
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">5</span> Bob fff <span class="synConstant">1</span> <span class="synConstant">345</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># pandas 変数名を使用 実はf文字列でも行ける</span>
target = <span class="synConstant">'Bob'</span>
df.query(f<span class="synConstant">"name=='{target}'"</span>)
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">5</span> Bob fff <span class="synConstant">1</span> <span class="synConstant">345</span>
</pre>
<h2 id="数字が入っている文字列型の場合">数字が入っている文字列型の場合</h2>
<p>データのうち、id_codeカラムが"123"であるものを抽出しよう。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># pandas 直接値を指定</span>
df.query(<span class="synConstant">"id_code=='123'"</span>)
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">3</span> Charlie ddd <span class="synConstant">3</span> <span class="synConstant">123</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># dask 直接値を指定</span>
ddf.query(<span class="synConstant">"id_code=='123'"</span>).compute()
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">3</span> Charlie ddd <span class="synConstant">3</span> <span class="synConstant">123</span>
</pre>
<p>ここまでは何も問題ない。<br/>
ところが、変数名を使用すると状況が変わってくる。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># pandas 変数名を使用 @</span>
code = <span class="synConstant">'123'</span>
df.query(f<span class="synConstant">"id_code==@code"</span>)
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">3</span> Charlie ddd <span class="synConstant">3</span> <span class="synConstant">123</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># dask 変数名を使用 f文字列 失敗例</span>
code = <span class="synConstant">'123'</span>
ddf.query(f<span class="synConstant">"id_code=={code}"</span>).compute()
<span class="synComment"># --------------------</span>
Empty DataFrame
Columns: [name, item, number, id_code]
Index: []
</pre>
<p>query関数の結果は空のDataFrameになる。<br/>
エラーが出るほうがまだハッキリ間違い箇所が分かる分だけ修正しやすいかもしれない……<br/>
これもquery関数の中にある文字列を単独で表示させるとよく分かる。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">print</span>(f<span class="synConstant">"id_code=={code}"</span>)
<span class="synComment"># --------------------</span>
id_code==<span class="synConstant">123</span>
</pre>
<p>これをquery関数に入れると、id_codeが数字の123に等しいものを探してしまう。だから該当する行は無く、空のDataFrameが返る。<br/>
なお、pandasでは数字(より正確には10進数の整数<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%EB">リテラル</a>)の先頭に0をつけてはいけないので、<code>012</code>で同じことをやると違う状況になる。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># pandasでは数字の先頭に0をつけてはいけない</span>
x = <span class="synConstant">012</span>
<span class="synComment"># --------------------</span>
File <span class="synConstant">"<ipython-input-27-d581e4a9bb8c>"</span>, line <span class="synConstant">2</span>
x = <span class="synConstant">012</span>
^
<span class="synType">SyntaxError</span>: leading zeros <span class="synStatement">in</span> decimal integer literals are <span class="synStatement">not</span> permitted; use an 0o prefix <span class="synStatement">for</span> octal integers
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># dask 変数名を使用 f文字列 失敗例その2</span>
code = <span class="synConstant">'012'</span>
ddf.query(f<span class="synConstant">"id_code=={code}"</span>).compute()
<span class="synComment"># --------------------</span>
エラー。長いので折りたたみます。
</pre>
<p><details><summary>クリックでエラー内容を表示</summary><div></p>
<hr />
<pre class="code" data-lang="" data-unlink> SyntaxError Traceback (most recent call last)
/usr/local/lib/python3.8/site-packages/dask/dataframe/utils.py in raise_on_meta_error(funcname, udf)
194 try:
--> 195 yield
196 except Exception as e:
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in _emulate(func, udf, *args, **kwargs)
6570 with raise_on_meta_error(funcname(func), udf=udf), check_numeric_only_deprecation():
-> 6571 return func(*_extract_meta(args, True), **_extract_meta(kwargs, True))
6572
/usr/local/lib/python3.8/site-packages/dask/utils.py in __call__(self, _methodcaller__obj, *args, **kwargs)
1102 def __call__(self, __obj, *args, **kwargs):
-> 1103 return getattr(__obj, self.method)(*args, **kwargs)
1104
/usr/local/lib/python3.8/site-packages/pandas/core/frame.py in query(self, expr, inplace, **kwargs)
3339 kwargs["target"] = None
-> 3340 res = self.eval(expr, **kwargs)
3341
/usr/local/lib/python3.8/site-packages/pandas/core/frame.py in eval(self, expr, inplace, **kwargs)
3469
-> 3470 return _eval(expr, inplace=inplace, **kwargs)
3471
/usr/local/lib/python3.8/site-packages/pandas/core/computation/eval.py in eval(expr, parser, engine, truediv, local_dict, global_dict, resolvers, level, target, inplace)
340
--> 341 parsed_expr = Expr(expr, engine=engine, parser=parser, env=env)
342
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in __init__(self, expr, engine, parser, env, level)
786 self._visitor = _parsers[parser](self.env, self.engine, self.parser)
--> 787 self.terms = self.parse()
788
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in parse(self)
805 """
--> 806 return self._visitor.visit(self.expr)
807
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
393 e.msg = "Python keyword not valid identifier in numexpr query"
--> 394 raise e
395
/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py in visit(self, node, **kwargs)
389 try:
--> 390 node = ast.fix_missing_locations(ast.parse(clean))
391 except SyntaxError as e:
/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ast.py in parse(source, filename, mode, type_comments, feature_version)
46 # Else it should be an int giving the minor version for 3.x.
---> 47 return compile(source, filename, mode, flags,
48 _feature_version=feature_version)
SyntaxError: invalid syntax (<unknown>, line 1)
The above exception was the direct cause of the following exception:
ValueError Traceback (most recent call last)
<ipython-input-28-5004d24aebb2> in <module>
1 # dask 変数名を使用 f文字列 失敗例その2
2 code = '012'
----> 3 ddf.query(f"id_code=={code}").compute()
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in query(self, expr, **kwargs)
5178 2 1 3 2
5179 """
-> 5180 return self.map_partitions(M.query, expr, **kwargs)
5181
5182 @derived_from(pd.DataFrame)
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in map_partitions(self, func, *args, **kwargs)
873 None as the division.
874 """
--> 875 return map_partitions(func, self, *args, **kwargs)
876
877 @insert_meta_param_description(pad=12)
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in map_partitions(func, meta, enforce_metadata, transform_divisions, align_dataframes, *args, **kwargs)
6639 dfs = [df for df in args if isinstance(df, _Frame)]
6640
-> 6641 meta = _get_meta_map_partitions(args, dfs, func, kwargs, meta, parent_meta)
6642 if all(isinstance(arg, Scalar) for arg in args):
6643 layer = {
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in _get_meta_map_partitions(args, dfs, func, kwargs, meta, parent_meta)
6750 # Use non-normalized kwargs here, as we want the real values (not
6751 # delayed values)
-> 6752 meta = _emulate(func, *args, udf=True, **kwargs)
6753 meta_is_emulated = True
6754 else:
/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py in _emulate(func, udf, *args, **kwargs)
6569 """
6570 with raise_on_meta_error(funcname(func), udf=udf), check_numeric_only_deprecation():
-> 6571 return func(*_extract_meta(args, True), **_extract_meta(kwargs, True))
6572
6573
/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/contextlib.py in __exit__(self, type, value, traceback)
129 value = type()
130 try:
--> 131 self.gen.throw(type, value, traceback)
132 except StopIteration as exc:
133 # Suppress StopIteration *unless* it's the same exception that
/usr/local/lib/python3.8/site-packages/dask/dataframe/utils.py in raise_on_meta_error(funcname, udf)
214 )
215 msg = msg.format(f" in `{funcname}`" if funcname else "", repr(e), tb)
--> 216 raise ValueError(msg) from e
217
218
ValueError: Metadata inference failed in `query`.
You have supplied a custom function and Dask is unable to
determine the type of output that that function returns.
To resolve this please provide a meta= keyword.
The docstring of the Dask function you ran should have more information.
Original error is below:
------------------------
SyntaxError('invalid syntax', ('<unknown>', 1, 13, 'id_code ==0 12 \n'))
Traceback:
---------
File "/usr/local/lib/python3.8/site-packages/dask/dataframe/utils.py", line 195, in raise_on_meta_error
yield
File "/usr/local/lib/python3.8/site-packages/dask/dataframe/core.py", line 6571, in _emulate
return func(*_extract_meta(args, True), **_extract_meta(kwargs, True))
File "/usr/local/lib/python3.8/site-packages/dask/utils.py", line 1103, in __call__
return getattr(__obj, self.method)(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/frame.py", line 3340, in query
res = self.eval(expr, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/frame.py", line 3470, in eval
return _eval(expr, inplace=inplace, **kwargs)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/eval.py", line 341, in eval
parsed_expr = Expr(expr, engine=engine, parser=parser, env=env)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 787, in __init__
self.terms = self.parse()
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 806, in parse
return self._visitor.visit(self.expr)
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 394, in visit
raise e
File "/usr/local/lib/python3.8/site-packages/pandas/core/computation/expr.py", line 390, in visit
node = ast.fix_missing_locations(ast.parse(clean))
File "/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ast.py", line 47, in parse
return compile(source, filename, mode, flags,</pre>
<p></div></details></p>
<p>正しい結果を得るためには、f文字列の中、123の外側に引用符を書く必要がある。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># dask 変数名を使用 f文字列 成功例</span>
code = <span class="synConstant">'123'</span>
ddf.query(f<span class="synConstant">"id_code=='{code}'"</span>).compute()
<span class="synComment"># '012' の場合も同様なので、省略する。</span>
<span class="synComment"># --------------------</span>
name item number id_code
<span class="synConstant">1</span> Bob bbb <span class="synConstant">2</span> <span class="synConstant">123</span>
<span class="synConstant">3</span> Charlie ddd <span class="synConstant">3</span> <span class="synConstant">123</span>
</pre>
<h2 id="まとめ">まとめ</h2>
<p>「pandas側で<code>@variable_name</code>と書く代わりに、daskでは<code>{variable_name}</code>と書く」という意識だと失敗する。<br/>
<strong>「変数を使わずにquery関数の引数の文字列を書くにはどうすればよいか」「それをf文字列で実現するにはどうすればよいか」</strong> を考えれば良さそう。長々と色々な例を書いてきたけど、要約すれば上記のとおりになる。<br/>
daskのqueryの場合、扱っているのは普通のf文字列なので、文字列内の変数を展開したときに期待通りになっていれば良いというわけだ。</p>
<p>……というかここまで書いて気づいたけど、
pandasのqueryも引数に取るのはただの文字列なんだから、</p>
<pre class="code lang-python" data-lang="python" data-unlink>num = <span class="synConstant">2</span>
df.query(f<span class="synConstant">"number=={num}"</span>)
</pre>
<p>が行けるとか書いてたけど、ただの文字列の書き方の違いじゃん。引数の文字列をそのまま書くかf文字列の展開を使って書くかの違いじゃん。<br/>
pandasのqueryといえば@を使うのが当たり前で、f文字列でも上手くいくのが意外で特別なことのように見えてしまった。
しかし、むしろ@を使った記法の方が、引数文字列の中身が違うから特殊だった(pandasの特殊な記法)。f文字列による指定は普通の<a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>が分かっていれば自然な、一般的な話であった。</p>
<p>それでは。</p>
soratokimitonoaidani
docker image pruneで「何日前より前のイメージを全て削除」を指定する
hatenablog://entry/4207112889956193199
2023-01-21T19:27:20+09:00
2023-01-21T19:27:20+09:00 Dockerイメージを作ってAmazon ECSにプッシュ、を繰り返していた。その結果、docker imagesコマンドを打つと、使っていない(最新でない)dockerイメージが大量に表示されてわかりにくくなってしまった。イメージを削除する方法を調べた。 Q1. Docker image を多数一斉に消すためのコマンドは何か? Q2. デフォルトだとどの範囲が消えるの? Q3 untilの使い方は? Q4 3日前よりも前に作られた宙ぶらりんな(dangling)imageを全部消したい。どのようにコマンドを打てばよいか? Q1. Docker image を多数一斉に消すためのコマンドは何か…
<p>Dockerイメージを作って<a class="keyword" href="http://d.hatena.ne.jp/keyword/Amazon">Amazon</a> ECSにプッシュ、を繰り返していた。その結果、docker imagesコマンドを打つと、使っていない(最新でない)dockerイメージが大量に表示されてわかりにくくなってしまった。イメージを削除する方法を調べた。</p>
<ul class="table-of-contents">
<li><a href="#Q1-Docker-image-を多数一斉に消すためのコマンドは何か">Q1. Docker image を多数一斉に消すためのコマンドは何か?</a></li>
<li><a href="#Q2-デフォルトだとどの範囲が消えるの">Q2. デフォルトだとどの範囲が消えるの?</a></li>
<li><a href="#Q3-untilの使い方は">Q3 untilの使い方は?</a></li>
<li><a href="#Q4-3日前よりも前に作られた宙ぶらりんなdanglingimageを全部消したいどのようにコマンドを打てばよいか">Q4 3日前よりも前に作られた宙ぶらりんな(dangling)imageを全部消したい。どのようにコマンドを打てばよいか?</a></li>
</ul>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20230121/20230121192526.png" width="960" height="540" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h2 id="Q1-Docker-image-を多数一斉に消すためのコマンドは何か">Q1. Docker image を多数一斉に消すためのコマンドは何か?</h2>
<p>A1. docker image prune</p>
<p>ドキュメントはこちら。<br/>
<a href="https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/image_prune/">https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/image_prune/</a><br/>
…… docker.com の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>の下に無いんだけど、これって公式なのか? 個人的な翻訳なのか? 分からん。<br/>
<a href="https://docs.docker.jp/engine/reference/commandline/image_prune.html">https://docs.docker.jp/engine/reference/commandline/image_prune.html</a><br/>
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>にdockerが入っているのはこっちですね。</p>
<p>docker image rm もイメージを削除するコマンドだが、イメージのidを指定する必要があるので、一定条件に当てはまるイメージをまとめて削除はできない。</p>
<h2 id="Q2-デフォルトだとどの範囲が消えるの">Q2. デフォルトだとどの範囲が消えるの?</h2>
<p>A2. 宙ぶらりんなイメージ = 「タグを持たず、他のコンテナからも参照されないイメージ」</p>
<p>全ての宙ぶらりんな(dangling)イメージを削除します。(<a href="https://docs.docker.jp/engine/reference/commandline/image_prune.html">先ほどのドキュメント</a>より)<br/>
って言われても分からないな。別のページの説明によれば「タグを持たず、他のコンテナからも参照されないイメージ」のこと。</p>
<blockquote><p>宙ぶらりんイメージとは、タグを持たず、他のコンテナからも参照されないイメージです。<br/>
<a href="https://docs.docker.jp/config/pruning.html">https://docs.docker.jp/config/pruning.html</a></p></blockquote>
<h2 id="Q3-untilの使い方は">Q3 untilの使い方は?</h2>
<p>A3. ある時点より手前の宙ぶらりんなイメージを全部削除する。</p>
<p>以下2つの方式が可能。</p>
<ul>
<li>具体的なタイムスタンプを指定して「until=2017-01-04T00:00:00」とするか、</li>
<li>現在からの相対時間で「until=240h」とするか</li>
</ul>
<h2 id="Q4-3日前よりも前に作られた宙ぶらりんなdanglingimageを全部消したいどのようにコマンドを打てばよいか">Q4 3日前よりも前に作られた宙ぶらりんな(dangling)imageを全部消したい。どのようにコマンドを打てばよいか?</h2>
<p>A4. until=3d も until=3D も不可。until=72hとする必要あり。</p>
<p>3日は3dで行けるのかなーとやってみたら、</p>
<pre class="code" data-lang="" data-unlink>> docker image prune --filter until=3d
WARNING! (省略。yを入力して実行する)
Error response from daemon: failed to parse as time or duration: "3d"</pre>
<p>とエラーになったので、「3日を指定する方法ってどうするんだろう」と思ってドキュメントを見ると、こう書いてあった。</p>
<blockquote><p>デーモンが動作しているマシン上の時刻からの相対時間を、 Go duration 文字列(例: 10m 、 1h3-m )で計算します。
<a href="https://docs.docker.jp/engine/reference/commandline/image_prune.html">https://docs.docker.jp/engine/reference/commandline/image_prune.html</a></p></blockquote>
<p>じゃあこの書式を調べようと思って「Go duration 文字列」で検索しても、情報が出てこない。「Go duration」で調べると出てくる。<br/>
<a href="https://leben.mobi/go/time/go-programming/#timeDuration">https://leben.mobi/go/time/go-programming/#timeDuration</a><br/>
Go言語でtimeパッケージのtime.Duration型は、2つの時刻の差を表す型である。<a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>だとdatetime.timedeltaに相当するものだな。<br/>
そしてその単位は最大で"h(時間)"までしか対応していない。</p>
<blockquote><p>Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".<br/>
<a href="https://pkg.go.dev/time#Duration">https://pkg.go.dev/time#Duration</a></p></blockquote>
<p>というわけで3日をそのまま指定することはできない。72時間に単位換算して、</p>
<pre class="code" data-lang="" data-unlink>> docker image prune --filter until=72h</pre>
<p>とするのが正解だ。</p>
<p>慣れないDockerを使い始めた初心者の覚え書きでした。それでは。</p>
soratokimitonoaidani
2022年の振り返り
hatenablog://entry/4207112889950559881
2023-01-02T23:49:22+09:00
2023-01-02T23:53:09+09:00 2022年の振り返り 一人暮らし 仕事 自己学習 ゲーム 音ゲー 音ゲー以外 歯 総評 実家にパソコンを持って帰ってきたけど、考えてみるとここにはパソコン作業をするための机がない。引っ越すときに机を持ち出したからだ。変な姿勢で書いている。 ※ 今年・去年・来年がややこしくなりそうなので、2022年・2023年で表記を統一します。 一人暮らし 2022年の個人的に最大の変化。6月から一人暮らしを始めた。 面倒くさがりな性格のせいで、「一応生きていくことはできるが、使いにくくて不便」という状況になっているので、どうやって住みやすい暮らしにすれば良いかな…… 仕事 主なプロジェクトは3つ。 第1のプ…
<p>2022年の振り返り</p>
<ul class="table-of-contents">
<li><a href="#一人暮らし">一人暮らし</a></li>
<li><a href="#仕事">仕事</a></li>
<li><a href="#自己学習">自己学習</a></li>
<li><a href="#ゲーム">ゲーム</a><ul>
<li><a href="#音ゲー">音ゲー</a></li>
<li><a href="#音ゲー以外">音ゲー以外</a></li>
</ul>
</li>
<li><a href="#歯">歯</a></li>
<li><a href="#総評">総評</a></li>
</ul>
<p>実家にパソコンを持って帰ってきたけど、考えてみるとここにはパソコン作業をするための机がない。引っ越すときに机を持ち出したからだ。変な姿勢で書いている。</p>
<p>※ 今年・去年・来年がややこしくなりそうなので、2022年・2023年で表記を統一します。</p>
<h2 id="一人暮らし">一人暮らし</h2>
<p>2022年の個人的に最大の変化。6月から一人暮らしを始めた。<br/>
面倒くさがりな性格のせいで、「一応生きていくことはできるが、使いにくくて不便」という状況になっているので、どうやって住みやすい暮らしにすれば良いかな……</p>
<h2 id="仕事">仕事</h2>
<p>主なプロジェクトは3つ。<br/>
第1のプロジェクトは4月まで。あんま覚えてない……仕事のコミュニケーションって大変ですねというに留めておくか。<br/>
第2のプロジェクトは9月途中まで。ここは大変だった。火消しに追われて、現職への入社以来初めて残業時間が要注意ラインを超えた。けど、振り返ってみると期待以上の働きができたと思う。チームリーダーとしての面目躍如である。データ分析系なら少人数チームの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%CA%C4%BD%B4%C9%CD%FD">進捗管理</a>して成果上げることできるんだな。<br/>
第3のプロジェクトは継続中。これまでは小規模データを手元(ローカルマシン上)で解析することが多かったが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a>系のシステム構築だったりで初見要素が多い。まぁ慣れないなという感想に尽きる。<br/>
業務中は基本的にあんまり細かい反省はしないことが多い。「今の自分にはXXXが足りていない。その対処としてYYYを実行した。その結果としてZZZという成果を上げた」みたいな細かい分析はせずに「今の自分にできることをできる範囲で頑張るわ」という感じで生きているので、構造化面接とかで掘り下げられると困ってしまう。みんなそんな緻密に考えて仕事してるの?<br/>
職位も1個上がったけど、このままやっていくか考え中なので、データサイエンティストを探している会社がいましたら連絡ください。話しましょう。あ、エージェントは間に合ってるので不要です。</p>
<p>有給休暇も年5日(法律的に取得が義務付けられている最低ライン)だった。わざわざ有給休暇を取ってやることが思いつかないという理由もあり、取ったら業務の進捗に遅れをきたすかなと言う心配もあり。</p>
<h2 id="自己学習">自己学習</h2>
<p>なんか2022年は全然やらなかった。<br/>
この技術ブログも復活させようと何度か月次目標に書いてみたりもしたのだが、実際の作業が伴わず記事を書き上げられなかった。<br/>
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a>も<a href="https://atcoder.jp/users/Linus/history?contestType=algo">2022年に出たのは9月の1回だけ</a>。<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCJ">GCJ</a>は辛うじて毎年恒例で参加したけど。<br/>
社内で週1で開催されている勉強会も、業務の打ち合わせとかぶるので参加できなくなって、そのまま不参加がデフォルトになってしまった。うーーん。<br/>
原因はよく分からない。コロナ禍のせい(リアルの勉強会が無くなった)か、一人暮らししたせい(暇があったらゲームするかゲーセンに行くかするようになった)か、転職したせい(業務している時間が長くなった)のどれかだと思うけど。<br/>
ともあれ、原因を分析するよりも事態を改善するのが先だと思うので、来年は技術ブログ復活の年にしたい……。<br/>
活発に技術の勉強をしているコミュニティを見つけて参加するのが良いのかなとボンヤリ思っている。<br/>
「技術の自己学習をしなければいけないと思っているようではダメ。真のエンジニアは勉強したくて仕方がないから暇さえあれば勉強してる」みたいな言説もあるけど、黙殺させてもらうことにする。</p>
<p>ついでにいうと読書も全然しなくなったんだよな。ここ1年で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%AB%B0%E6%A5%EA%A5%E7%A5%A6">朝井リョウ</a>の「何者」を読んだくらいじゃないか?</p>
<h2 id="ゲーム">ゲーム</h2>
<h3 id="音ゲー"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BB%A5%B2%A1%BC">音ゲー</a></h3>
<p>数年に1回ある「メインの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BB%A5%B2%A1%BC">音ゲー</a>が移り変わる」が発生した。
2022年の途中までは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E9%A5%DE%A5%CB">ドラマニ</a>がメインだった。HIGH-VOLTAGEが稼働したのが2021年4月だ。そのちょっと前(NEX+AGE後半。2020年秋頃?)から<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E9%A5%DE%A5%CB">ドラマニ</a>メインだった。<br/>
けど、気づいたら<a class="keyword" href="http://d.hatena.ne.jp/keyword/DDR">DDR</a>に移行していた。9〜10月ごろか?<br/>
<a href="http://gsv.fun/ja/highvoltage/897/d">HIGH-VOLTAGE gsv記録</a><br/>
5500目標だったけど達成しないうちに新作にFUZZ-UPに。こうなるとスキルが0にリセットされるのでモチベがダルいね。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/DDR">DDR</a>はskill attackを詰めてみたけど、2015年当時→2022年末で、14〜15のスコア能力は多少伸びたらしいので嬉しい。ただ17〜18のクリア能力は多分当時ほど戻っていない。今は18弱がクリアできるかできないかの実力だ。</p>
<p><a href="http://skillattack.com/sa4_ddr2014/dancer_profile.php?ddrcode=11086793">skill attack 2015当時</a><br/>
<a href="http://skillattack.com/sa4/dancer_skillpoint.php?_=detail&ddrcode=11086793&date=20221226">skill attack 2022末</a></p>
<h3 id="音ゲー以外"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BB%A5%B2%A1%BC">音ゲー</a>以外</h3>
<ul>
<li>原神:<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CB%C1%B8%B1%BC%D4">冒険者</a>ランク59まで行ったのに螺旋最終12章を倒せないのって俺くらいじゃないですかね……まぁイベントが次々配信されているので惰性で続けている感覚。やめようかなとたまに思いつつも続けている。</li>
<li>オクトパストラベラー:2022年5月に買って、70時間ほど。シナリオは終盤に来たけどサブシナリオは全然取れていない。続編の2が2023年2月24日発売なのでその前にクリアしたいが……</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B1%A4%CE%A5%AB%A1%BC%A5%D3%A5%A3">星のカービィ</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%B9%A5%AB%A5%D0%A5%EA%A1%BC">ディスカバリー</a>:2022年5月に買って、最初の方で止めている。</li>
</ul>
<h2 id="歯">歯</h2>
<p>2022年はなぜか歯の不調に悩まされた。</p>
<p>2022年の初めのほう、夕方になったら右下の歯がすごい痛むのに歯医者行っても異常なしと言われる(おそらく非歯原性歯痛)<br/>
→対処が分からなくて調べる<br/>
→何か調べたら筋膜を押すと良いらしい<br/>
→奥歯を外から押し込みすぎて歯並びが変わってしまったっぽい<br/>
→右上の歯に力が加わってフィステルになった(5月)</p>
<p>その後も色々とあり、
現状、口の中からやたらとパキパキという音がなるようになってしまった。
噛み合わせも安定しないし、舌が歯に変に当たって舌炎になることも多いし。歯医者は現状で行ってるから歯科矯正するか。残りの人生をこのめっちゃ不便な状態で過ごすことを考えたら必要な処置だとは思う。けど費用がかなり高い……
タイムマシンがあったら「奥歯を押し込んで歯並びを変えるのをやめろ」って過去の俺に言いたい。</p>
<h2 id="総評">総評</h2>
<p>一人暮らしして変わるかなと思ったけどかなり順当な変化だった。一人暮らしして生きるためのこと(炊事・洗濯・掃除)をやり、気兼ねなく外出できるようになったので日本酒と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BB%A5%B2%A1%BC">音ゲー</a>要素が増えた。</p>
<p>新規追加されたのはスポーツジム・筋トレ・<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C6%A5%A4%A5%F3">プロテイン</a>の要素くらいか。
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D4%A5%AB%A5%C1%A5%E5%A5%A6">ピカチュウ</a>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%A4%A5%C1%A5%E5%A5%A6">ライチュウ</a>になったみたいな感じだよなって年末から思っている。(順当な・予想できる進化だよなー、ということ)もう少し意外性のある進化をしても良い気がする。<br/>
せっかく自分だけで完全に自由に使える時間と空間があるわけで。その自由が続く時間は(願わくは)そう長くはないので、使い方を考えていきたいね。</p>
<p>ひとまず以上です。</p>
soratokimitonoaidani
seabornのswarmplotで点の色を直接指定する
hatenablog://entry/13574176438097774463
2022-05-31T23:18:40+09:00
2023-01-26T22:18:29+09:00 【注意】この記事は完成度70%くらいです。一部の図が張れていないので正しく表示されません。気が向いたら読める形にします。 seabornが好きだ。 特に指定しなくても、大抵の場合はきれいな色で美しいグラフを描画してくれるし、 matplotlibでは簡単に描けないような複雑なグラフも一発で作れる。 seabornを使って多数のグラフを別々に作った場合に、色を合わせたい場合がある。 例えば「1月のデータは赤、2月は青」という決まりでグラフを書きたい場合である。 一部のグラフでその決まりが崩れていると、読んで理解するのに時間がかかってしまうだろう。 そこで今回は、swarmplotで色を直接指定す…
<p><span style="font-size: 150%">【注意】この記事は完成度70%くらいです。一部の図が張れていないので正しく表示されません。気が向いたら読める形にします。
</span></p>
<p>seabornが好きだ。<br/>
特に指定しなくても、大抵の場合はきれいな色で美しいグラフを描画してくれるし、
matplotlibでは簡単に描けないような複雑なグラフも一発で作れる。</p>
<p>seabornを使って多数のグラフを別々に作った場合に、色を合わせたい場合がある。<br/>
例えば「1月のデータは赤、2月は青」という決まりでグラフを書きたい場合である。
一部のグラフでその決まりが崩れていると、読んで理解するのに時間がかかってしまうだろう。
そこで今回は、swarmplotで色を直接指定する方法について調べた。<br/>
<a href="https://seaborn.pydata.org/generated/seaborn.swarmplot.html">seaborn公式ドキュメントのswamplot関数の説明はこちら</a></p>
<ul class="table-of-contents">
<li><a href="#準備">準備</a></li>
<li><a href="#1つ目軸に指定したカテゴリに合わせて色を指定したい">1つ目:軸に指定したカテゴリに合わせて色を指定したい</a></li>
<li><a href="#2つ目軸に指定したものとは別のカテゴリに合わせて色を指定したい">2つ目:軸に指定したものとは別のカテゴリに合わせて色を指定したい</a></li>
<li><a href="#余談color変数の挙動">余談:color変数の挙動</a></li>
</ul>
<h2 id="準備">準備</h2>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> seaborn <span class="synStatement">as</span> sns
<span class="synPreProc">import</span> matplotlib
<span class="synComment"># --------------------</span>
Duplicate key <span class="synStatement">in</span> <span class="synIdentifier">file</span> PosixPath(<span class="synConstant">'/usr/local/lib/python3.8/site-packages/matplotlib/mpl-data/matplotlibrc'</span>), line <span class="synConstant">258</span> (<span class="synConstant">'font.family : Hiragino sans'</span>)
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 動作環境の確認</span>
<span class="synComment"># print(pd.__version__)</span>
<span class="synComment"># print(np.__version__)</span>
<span class="synIdentifier">print</span>(sns.__version__)
<span class="synIdentifier">print</span>(matplotlib.__version__)
!python3 --version
<span class="synComment"># --------------------</span>
<span class="synConstant">0.11</span>.<span class="synConstant">0</span>
<span class="synConstant">3.3</span>.<span class="synConstant">1</span>
Python <span class="synConstant">3.8</span>.<span class="synConstant">5</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># https://seaborn.pydata.org/generated/seaborn.swarmplot.html</span>
<span class="synComment"># ★styleの設定どうする?</span>
tips = sns.load_dataset(<span class="synConstant">"tips"</span>)
tips.dtypes
<span class="synComment"># --------------------</span>
total_bill float64
tip float64
sex category
smoker category
day category
time category
size int64
dtype: <span class="synIdentifier">object</span>
</pre>
<p>※上記のdtypesで、dayなどのカラムが文字列型ではなくカテゴリカル型であることに注意、<br/>
(文字列型だと異なる挙動をする可能性もある。今回は検証していない。)</p>
<p>seabornのswarmplotで、色を指定する方法は2つある。<br/>
1つが、xとyのうち片方に指定したカテゴリに合わせて色を指定する方法である。<br/>
もう1つが、軸に指定したものとは別のカテゴリに合わせて色を指定する方法である。<br/>
この順に紹介する。</p>
<h2 id="1つ目軸に指定したカテゴリに合わせて色を指定したい">1つ目:軸に指定したカテゴリに合わせて色を指定したい</h2>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, data=tips)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20221118/20221118004532.png" width="383" height="262" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>xにdayを指定すると、xに応じて点に色が付く。<br/>
この色を直接指定したい。<br/>
例えば、Thurを赤で、Friを黒で、……のように具体的な色の希望があった場合、どうすればよいのか?<br/>
色を単純に入れ替えたいだけならば、hue_orderで順序を指定すれば良い……かと思ったが、hue_orderを用いてもx軸上の並びは変わらなかった。<br/>
(たぶん元データの中でdayのデータ型がcategoryなので、hue_orderを指定しても無視されて、categoryが優先される?)</p>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, hue_order=[<span class="synConstant">"Fri"</span>, <span class="synConstant">"Sun"</span>, <span class="synConstant">"Sat"</span>, <span class="synConstant">"Thur"</span>], data=tips)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20221118/20221118004713.png" width="383" height="262" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>正解は
引数のうち、paletteを指定すればよい。</p>
<blockquote><p><strong>palette</strong> palette name, list, or dict<br/>
Colors to use for the different levels of the hue variable. Should be something that can be interpreted by <a href="https://seaborn.pydata.org/generated/seaborn.color_palette.html#seaborn.color_palette">color_palette()</a>, or a dictionary mapping hue levels to matplotlib colors.<br/>
<a href="https://seaborn.pydata.org/generated/seaborn.swarmplot.html">https://seaborn.pydata.org/generated/seaborn.swarmplot.html</a> より</p></blockquote>
<p>palette引数に指定できるのは、paletteの名前かlistかdictである。<br/>
「paletteの名前」はpastelやbrightなどである。<a href="https://seaborn.pydata.org/tutorial/color_palettes.html?highlight=pastel#qualitative-color-palettes">カラーパレットに関する公式ドキュメントの説明</a>を参照。今回は具体的な色を指定したいので「paletteの名前」は使えない。
listを使って指定してみよう。以下のようになる。
listの中身である「具体的なそれぞれの色」の指定方法はいくつかあるが、今回は色の名前(文字列)を使う。</p>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, palette=[<span class="synConstant">"purple"</span>, <span class="synConstant">"green"</span>, <span class="synConstant">"orange"</span>, <span class="synConstant">"skyblue"</span>], data=tips)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20221118/20221118004746.png" width="383" height="262" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>リストだと、どの値がどの色になるのか分かりづらい。dictも指定できて、この場合は対応関係が明確になる。</p>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, palette={<span class="synConstant">"Thur"</span>: <span class="synConstant">"purple"</span>, <span class="synConstant">"Fri"</span>: <span class="synConstant">"green"</span>, <span class="synConstant">"Sat"</span>: <span class="synConstant">"orange"</span>, <span class="synConstant">"Sun"</span>: <span class="synConstant">"skyblue"</span>}, data=tips)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20221118/20221118004727.png" width="383" height="262" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>ちなみにpaletteをリストで指定し、長さが足りない場合、繰り返しになる</p>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, palette=[<span class="synConstant">"purple"</span>, <span class="synConstant">"green"</span>], data=tips)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20221118/20221118004757.png" width="383" height="262" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>辞書でkeyがない場合は、エラーになる。そのdayを何色で塗ればいいか分からないからね。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 辞書のkeyにFriがないのでエラー </span>
ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, palette={<span class="synConstant">"Thur"</span>: <span class="synConstant">"purple"</span>, <span class="synConstant">"Sat"</span>: <span class="synConstant">"orange"</span>, <span class="synConstant">"Sun"</span>: <span class="synConstant">"skyblue"</span>}, data=tips)
<span class="synComment"># --------------------</span>
---------------------------------------------------------------------------
</pre>
<pre><code>KeyError Traceback (most recent call last)
<ipython-input-9-c9f97ba5b082> in <module>
1 # 辞書のkeyにFriがないのでエラー
----> 2 ax = sns.swarmplot(x="day", y="total_bill", palette={"Thur": "purple", "Sat": "orange", "Sun": "skyblue"}, data=tips)
/usr/local/lib/python3.8/site-packages/seaborn/_decorators.py in inner_f(*args, **kwargs)
44 )
45 kwargs.update({k: arg for k, arg in zip(sig.parameters, args)})
---> 46 return f(**kwargs)
47 return inner_f
48
/usr/local/lib/python3.8/site-packages/seaborn/categorical.py in swarmplot(x, y, hue, data, order, hue_order, dodge, orient, color, palette, size, edgecolor, linewidth, ax, **kwargs)
2989 warnings.warn(msg, UserWarning)
2990
-> 2991 plotter = _SwarmPlotter(x, y, hue, data, order, hue_order,
2992 dodge, orient, color, palette)
2993 if ax is None:
/usr/local/lib/python3.8/site-packages/seaborn/categorical.py in __init__(self, x, y, hue, data, order, hue_order, dodge, orient, color, palette)
1171 """Initialize the plotter."""
1172 self.establish_variables(x, y, hue, data, orient, order, hue_order)
-> 1173 self.establish_colors(color, palette, 1)
1174
1175 # Set object attributes
/usr/local/lib/python3.8/site-packages/seaborn/categorical.py in establish_colors(self, color, palette, saturation)
304 else:
305 levels = self.hue_names
--> 306 palette = [palette[l] for l in levels]
307
308 colors = color_palette(palette, n_colors)
/usr/local/lib/python3.8/site-packages/seaborn/categorical.py in <listcomp>(.0)
304 else:
305 levels = self.hue_names
--> 306 palette = [palette[l] for l in levels]
307
308 colors = color_palette(palette, n_colors)
KeyError: 'Fri'
</code></pre>
<h2 id="2つ目軸に指定したものとは別のカテゴリに合わせて色を指定したい">2つ目:軸に指定したものとは別のカテゴリに合わせて色を指定したい</h2>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># Color the points using a second categorical variable:</span>
<span class="synComment"># 2つ目のカテゴリカル変数を用いて、点の色を指定する</span>
ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, hue=<span class="synConstant">"sex"</span>, data=tips)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20221118/20221118010651.png" width="383" height="262" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>xにdayというカテゴリカル変数を指定して、色のパラメータhueにはsexという別のカテゴリカル変数を指定するパターン。
色を単純に入れ替えたいだけならば、hue_orderで順序を指定すれば良い。以下のようになる。</p>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, hue=<span class="synConstant">"sex"</span>, data=tips, hue_order=[<span class="synConstant">"Female"</span>, <span class="synConstant">"Male"</span>])
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20221118/20221118010700.png" width="383" height="262" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>次に、「男性が緑、女性が紫」のように、直接色を指定したい場合はどうすればよいだろうか?
palette変数だよなー多分。<br/>
<strong>palette</strong> palette name, list, or dict<br/>
Colors to use for the different levels of the hue variable. Should be something that can be interpreted by <a href="https://seaborn.pydata.org/generated/seaborn.color_palette.html#seaborn.color_palette">color_palette()</a>, or a dictionary mapping hue levels to matplotlib colors.</p>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, hue=<span class="synConstant">"sex"</span>, palette=[<span class="synConstant">"green"</span>, <span class="synConstant">"purple"</span>], data=tips)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20221118/20221118010711.png" width="383" height="262" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>リストだと、どの値がどの色になるのか分かりづらい。dictも指定できて、この場合は対応関係が明確になる。</p>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, hue=<span class="synConstant">"sex"</span>, palette={<span class="synConstant">"Male"</span>: <span class="synConstant">"green"</span>, <span class="synConstant">"Female"</span>: <span class="synConstant">"purple"</span>}, data=tips)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20221118/20221118010721.png" width="383" height="262" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.to_hex.html</span>
<span class="synIdentifier">print</span>(matplotlib.colors.to_hex(<span class="synConstant">"green"</span>))
<span class="synIdentifier">print</span>(matplotlib.colors.to_hex(<span class="synConstant">"purple"</span>))
<span class="synComment"># --------------------</span>
<span class="synComment">#008000</span>
<span class="synComment">#800080</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, hue=<span class="synConstant">"sex"</span>, palette={<span class="synConstant">"Male"</span>: <span class="synConstant">"#008000"</span>, <span class="synConstant">"Female"</span>: <span class="synConstant">"#800080"</span>}, data=tips)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20221118/20221118010735.png" width="383" height="262" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<pre class="code lang-python" data-lang="python" data-unlink>
</pre>
<h2 id="余談color変数の挙動">余談:color変数の挙動</h2>
<p><strong>color</strong> matplotlib color, optional<br/>
Color for all of the elements, or seed for a gradient palette.</p>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, color=<span class="synConstant">"red"</span>, data=tips)
</pre>
<p><img src="output_29_0.png" alt="png" /></p>
<p>なぜかFemaleの色だけを赤に指定するっぽい?</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># Color the points using a second categorical variable:</span>
<span class="synComment"># 2つ目のカテゴリカル変数を用いて、点の色を指定する</span>
ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, hue=<span class="synConstant">"sex"</span>, color=<span class="synConstant">"red"</span>, data=tips)
</pre>
<p><img src="output_31_0.png" alt="png" /></p>
<p>ではcolorとして色の配列を渡せば良さそうに見えるが、それではエラーになる。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># Color the points using a second categorical variable:</span>
<span class="synComment"># 2つ目のカテゴリカル変数を用いて、点の色を指定する</span>
ax = sns.swarmplot(x=<span class="synConstant">"day"</span>, y=<span class="synConstant">"total_bill"</span>, hue=<span class="synConstant">"sex"</span>, color=[<span class="synConstant">"red"</span>, <span class="synConstant">"gray"</span>], data=tips)
<span class="synComment"># --------------------</span>
---------------------------------------------------------------------------
</pre>
<pre><code>ValueError Traceback (most recent call last)
<ipython-input-18-9e9e98d7907f> in <module>
2 # 2つ目のカテゴリカル変数を用いて、点の色を指定する
3
----> 4 ax = sns.swarmplot(x="day", y="total_bill", hue="sex", color=["red", "gray"], data=tips)
/usr/local/lib/python3.8/site-packages/seaborn/_decorators.py in inner_f(*args, **kwargs)
44 )
45 kwargs.update({k: arg for k, arg in zip(sig.parameters, args)})
---> 46 return f(**kwargs)
47 return inner_f
48
/usr/local/lib/python3.8/site-packages/seaborn/categorical.py in swarmplot(x, y, hue, data, order, hue_order, dodge, orient, color, palette, size, edgecolor, linewidth, ax, **kwargs)
2989 warnings.warn(msg, UserWarning)
2990
-> 2991 plotter = _SwarmPlotter(x, y, hue, data, order, hue_order,
2992 dodge, orient, color, palette)
2993 if ax is None:
/usr/local/lib/python3.8/site-packages/seaborn/categorical.py in __init__(self, x, y, hue, data, order, hue_order, dodge, orient, color, palette)
1171 """Initialize the plotter."""
1172 self.establish_variables(x, y, hue, data, orient, order, hue_order)
-> 1173 self.establish_colors(color, palette, 1)
1174
1175 # Set object attributes
/usr/local/lib/python3.8/site-packages/seaborn/categorical.py in establish_colors(self, color, palette, saturation)
293 colors = light_palette(color, n_colors)
294 elif self.default_palette == "dark":
--> 295 colors = dark_palette(color, n_colors)
296 else:
297 raise RuntimeError("No default palette specified")
/usr/local/lib/python3.8/site-packages/seaborn/palettes.py in dark_palette(color, n_colors, reverse, as_cmap, input)
541
542 """
--> 543 rgb = _color_to_rgb(color, input)
544 h, s, l = husl.rgb_to_husl(*rgb)
545 gray_s, gray_l = .15 * s, 15
/usr/local/lib/python3.8/site-packages/seaborn/palettes.py in _color_to_rgb(color, input)
465 color = xkcd_rgb[color]
466
--> 467 return mpl.colors.to_rgb(color)
468
469
/usr/local/lib/python3.8/site-packages/matplotlib/colors.py in to_rgb(c)
344 def to_rgb(c):
345 """Convert *c* to an RGB color, silently dropping the alpha channel."""
--> 346 return to_rgba(c)[:3]
347
348
/usr/local/lib/python3.8/site-packages/matplotlib/colors.py in to_rgba(c, alpha)
187 rgba = None
188 if rgba is None: # Suppress exception chaining of cache lookup failure.
--> 189 rgba = _to_rgba_no_colorcycle(c, alpha)
190 try:
191 _colors_full_map.cache[c, alpha] = rgba
/usr/local/lib/python3.8/site-packages/matplotlib/colors.py in _to_rgba_no_colorcycle(c, alpha)
263 raise ValueError(f"Invalid RGBA argument: {orig_c!r}")
264 if len(c) not in [3, 4]:
--> 265 raise ValueError("RGBA sequence should have length 3 or 4")
266 if not all(isinstance(x, Number) for x in c):
267 # Checks that don't work: `map(float, ...)`, `np.array(..., float)` and
ValueError: RGBA sequence should have length 3 or 4
</code></pre>
<pre class="code lang-python" data-lang="python" data-unlink>
</pre>
soratokimitonoaidani
pandasの時系列カラムの時刻を特定書式の文字列に変換する方法
hatenablog://entry/13574176438072070780
2022-03-12T12:00:00+09:00
2023-01-26T22:18:00+09:00 pandasの時系列カラムの時刻を特定書式の文字列に変換する方法 最近、このような状況が発生した。 データ分析用にダミーの簡単なデータを作る必要がある そのデータは時刻カラムを含む 時刻カラムは、タイムゾーンが設定されていて、UTCである 実際のデータの表示書式はYYYY-MM-DDThh:mm:ssZ の形式 (例 2020-07-27T02:12:40Z)であるため、ダミーデータについても同じ書式で作成したい どうすれば実現できるか? 注意:以下の説明で、「time zone naive = タイムゾーンが設定されていない」「time zone aware = タイムゾーンが設定されている…
<p>pandasの時系列カラムの時刻を特定書式の文字列に変換する方法</p>
<p>最近、このような状況が発生した。</p>
<ul>
<li>データ分析用にダミーの簡単なデータを作る必要がある</li>
<li>そのデータは時刻カラムを含む</li>
<li>時刻カラムは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>が設定されていて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/UTC">UTC</a>である</li>
<li>実際のデータの表示書式はYYYY-MM-DDThh:mm:ssZ の形式 (例 2020-07-27T02:12:40Z)であるため、ダミーデータについても同じ書式で作成したい</li>
<li>どうすれば実現できるか?</li>
</ul>
<p><strong>注意</strong>:以下の説明で、「time zone naive = <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>が設定されていない」「time zone aware = <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>が設定されている」という意味である。</p>
<ul class="table-of-contents">
<li><a href="#準備">準備</a></li>
<li><a href="#pandasの時刻カラムのタイムゾーン有無を調べる">pandasの時刻カラムのタイムゾーン有無を調べる</a></li>
<li><a href="#pandasの時刻カラムにタイムゾーンを設定する">pandasの時刻カラムにタイムゾーンを設定する</a></li>
<li><a href="#時刻が特定の書式になっているCSVを作る2つの方法">時刻が特定の書式になっているCSVを作る2つの方法</a><ul>
<li><a href="#時刻のデータをcsvに保存する際に時刻形式を変更する方法">時刻のデータをcsvに保存する際に、時刻形式を変更する方法</a></li>
<li><a href="#時刻のデータから希望する形式の文字列に変換する方法">時刻のデータから、希望する形式の文字列に変換する方法</a></li>
</ul>
</li>
</ul>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20220312/20220312111443.png" width="960" height="540" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<hr />
<p><a href="https://ufirst.jp/memo/2020/07/27/post-2638/">時刻表現 TやZの意味 | No pain,No gain.</a><br/>
で書いてあるように、2020-07-27T02:12:40Z という時刻の形式がある。
時刻を表現するときの国際的な規格として定められている、ISOもしくは<a class="keyword" href="http://d.hatena.ne.jp/keyword/RFC">RFC</a>に従った形式である。<br/>
ISO規格だと ISO 8601<br/>
<a class="keyword" href="http://d.hatena.ne.jp/keyword/RFC">RFC</a>規格だと<a class="keyword" href="http://d.hatena.ne.jp/keyword/RFC">RFC</a> 3339<br/>
らしい。(ほぼ同じと見ていいらしい。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Wikipedia">Wikipedia</a>の情報だけど)<br/>
pandasの時刻データをこの形で作る方法を調べた。</p>
<h2 id="準備">準備</h2>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd
<span class="synPreProc">import</span> datetime
pd.options.display.notebook_repr_html = <span class="synIdentifier">False</span> <span class="synComment"># jupyter notebook上での出力形式を制御するために書いています。無くても動きます。</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 動作環境の確認</span>
<span class="synIdentifier">print</span>(pd.__version__)
<span class="synComment"># --------------------</span>
<span class="synConstant">1.1</span>.<span class="synConstant">2</span>
</pre>
<p>時刻の列として、適当な時刻を3つほど作成する。datetime オブエジェクトを作り、日付と時までを適当に埋めよう。</p>
<pre class="code lang-python" data-lang="python" data-unlink>datetime_list = [
datetime.datetime(<span class="synConstant">2022</span>, <span class="synConstant">1</span>, <span class="synConstant">2</span>, <span class="synConstant">3</span>, <span class="synConstant">0</span>),
datetime.datetime(<span class="synConstant">2022</span>, <span class="synConstant">2</span>, <span class="synConstant">3</span>, <span class="synConstant">4</span>, <span class="synConstant">0</span>),
datetime.datetime(<span class="synConstant">2022</span>, <span class="synConstant">3</span>, <span class="synConstant">4</span>, <span class="synConstant">5</span>, <span class="synConstant">0</span>),
]
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>val_list = [<span class="synConstant">10</span>, <span class="synConstant">30</span>, <span class="synConstant">20</span>]
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime = pd.DataFrame({
<span class="synConstant">'datetime'</span> : datetime_list,
<span class="synConstant">'val'</span> : val_list
})
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime
<span class="synComment"># --------------------</span>
datetime val
<span class="synConstant">0</span> <span class="synConstant">2022</span>-<span class="synConstant">01</span>-<span class="synConstant">02</span> <span class="synConstant">03</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span> <span class="synConstant">10</span>
<span class="synConstant">1</span> <span class="synConstant">2022</span>-<span class="synConstant">02</span>-<span class="synConstant">03</span> <span class="synConstant">04</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span> <span class="synConstant">30</span>
<span class="synConstant">2</span> <span class="synConstant">2022</span>-<span class="synConstant">03</span>-<span class="synConstant">04</span> <span class="synConstant">05</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span> <span class="synConstant">20</span>
</pre>
<h2 id="pandasの時刻カラムのタイムゾーン有無を調べる">pandasの時刻カラムの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>有無を調べる</h2>
<p>自分の理解を整理するために、Q&Aの形式で書いていく。</p>
<p>Q1. このDataFrameのdatetimeカラムは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>がある時刻か、ない時刻か?<br/>
A1. <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>がない時刻である。</p>
<p>Q2. <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>がないということはどうして分かるのか?<br/>
A2. 以下2つの方法がある。<br/>
1つ目の方法は、カラムを調べることである。Series(カラム)に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>がないことは、Seriesのdtypeを見れば分かる。</p>
<blockquote><p><a href="https://pandas.pydata.org/docs/user_guide/timeseries.html#time-zone-series-operations">https://pandas.pydata.org/docs/user_guide/timeseries.html#time-zone-series-operations</a><br/>
A Series with time zone naive values is represented with a dtype of datetime64[ns].<br/>
A Series with a time zone aware values is represented with a dtype of datetime64[ns, tz] where tz is the time zone.</p></blockquote>
<p>拙訳:<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>が設定されていない値を持つSeriesは、<code>datetime64[ns]</code>というdtypeで表される。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>が設定されている値を持つSeriesは、<code>datetime64[ns, tz]</code>というdtypeで表される。ここで、tzは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>である。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime.dtypes
<span class="synComment"># --------------------</span>
datetime datetime64[ns]
val int64
dtype: <span class="synIdentifier">object</span>
</pre>
<p>2つ目の方法は、入っている時刻データを調べることである。</p>
<blockquote><p><a href="https://pandas.pydata.org/docs/user_guide/timeseries.html#time-zone-handling">https://pandas.pydata.org/docs/user_guide/timeseries.html#time-zone-handling</a><br/>
By default, pandas objects are time zone unaware:</p></blockquote>
<p>拙訳:デフォルトでは、pandasのオブジェクトには<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>が設定されていない。</p>
<p>この公式ドキュメントによれば、tzという属性がNoneなら<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>が設定されてないようだ。見てみよう。</p>
<pre class="code lang-python" data-lang="python" data-unlink>datetime1 = df_datetime.loc[<span class="synConstant">0</span>, <span class="synConstant">'datetime'</span>]
datetime1
<span class="synComment"># --------------------</span>
Timestamp(<span class="synConstant">'2022-01-02 03:00:00'</span>)
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 注:datetime1.tzと単に書くと、jupyter notebook上で結果のNoneが表示されないので、明示的にprintをつけてNoneを表示させている。</span>
<span class="synIdentifier">print</span>(datetime1.tz)
<span class="synComment"># --------------------</span>
<span class="synIdentifier">None</span>
</pre>
<p>どちらの方法にせよ、datetimeカラムには<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>が設定されていないことが分かった。
さて、欲しいデータは<a class="keyword" href="http://d.hatena.ne.jp/keyword/UTC">UTC</a>なので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>を設定しよう。</p>
<h2 id="pandasの時刻カラムにタイムゾーンを設定する">pandasの時刻カラムに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>を設定する</h2>
<p>Q3. 下記のコードでは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>を設定しようとして<code>Series.tz_localize()</code>を使っている。なんでエラーになるの?<br/>
A3. <code>Series.tz_localize()</code>はindexの時刻を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%AB%A5%E9%A5%A4%A5%BA">ローカライズ</a>処理するため。Seriesの値を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%AB%A5%E9%A5%A4%A5%BA">ローカライズ</a>するには、Series.dt.tz_localize()を使う。</p>
<blockquote><p><a href="https://pandas.pydata.org/docs/reference/api/pandas.Series.tz_localize.html">https://pandas.pydata.org/docs/reference/api/pandas.Series.tz_localize.html</a>
Localize tz-naive index of a Series or DataFrame to target time zone.<br/>
This operation localizes the Index. To localize the values in a timezone-naive Series, use Series.dt.tz_localize().</p></blockquote>
<p>拙訳:SeriesまたはDataFrameの、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>の設定されていないindexを指定された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%AB%A5%E9%A5%A4%A5%BA">ローカライズ</a>する。<br/>
この操作はインデックスを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%AB%A5%E9%A5%A4%A5%BA">ローカライズ</a>する。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>の設定されていないSeriesの値を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%AB%A5%E9%A5%A4%A5%BA">ローカライズ</a>するには、<code>Series.dt.tz_localize()</code>を使うこと。</p>
<p>……と公式ドキュメントに書いてあるとおりで、Seriesに対して直接<code>tz_localize</code>を実行しようとindexの時刻を変更しようとする。<br/>
今回はindexが時刻ではなくて数値なので「(indexの時刻を変更しようとしたら)indexが時刻じゃないんだけど」とエラーが出ている。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime[<span class="synConstant">'datetime_utc'</span>] = df_datetime[<span class="synConstant">'datetime'</span>].tz_localize(tz=<span class="synConstant">'UTC'</span>)
<span class="synComment"># --------------------</span>
---------------------------------------------------------------------------
<span class="synType">TypeError</span> Traceback (most recent call last)
<ipython-<span class="synIdentifier">input</span>-<span class="synConstant">10</span>-d343d953d675> <span class="synStatement">in</span> <module>
----> <span class="synConstant">1</span> df_datetime[<span class="synConstant">'datetime_utc'</span>] = df_datetime[<span class="synConstant">'datetime'</span>].tz_localize(tz=<span class="synConstant">'UTC'</span>)
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/pandas/core/generic.py <span class="synStatement">in</span> tz_localize(self, tz, axis, level, copy, ambiguous, nonexistent)
<span class="synConstant">9643</span> <span class="synStatement">if</span> level <span class="synStatement">not</span> <span class="synStatement">in</span> (<span class="synIdentifier">None</span>, <span class="synConstant">0</span>, ax.name):
<span class="synConstant">9644</span> <span class="synStatement">raise</span> <span class="synType">ValueError</span>(f<span class="synConstant">"The level {level} is not valid"</span>)
-> <span class="synConstant">9645</span> ax = _tz_localize(ax, tz, ambiguous, nonexistent)
<span class="synConstant">9646</span>
<span class="synConstant">9647</span> result = self.copy(deep=copy)
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/pandas/core/generic.py <span class="synStatement">in</span> _tz_localize(ax, tz, ambiguous, nonexistent)
<span class="synConstant">9625</span> <span class="synStatement">if</span> <span class="synIdentifier">len</span>(ax) > <span class="synConstant">0</span>:
<span class="synConstant">9626</span> ax_name = self._get_axis_name(axis)
-> <span class="synConstant">9627</span> <span class="synStatement">raise</span> <span class="synType">TypeError</span>(
<span class="synConstant">9628</span> f<span class="synConstant">"{ax_name} is not a valid DatetimeIndex or PeriodIndex"</span>
<span class="synConstant">9629</span> )
<span class="synType">TypeError</span>: index <span class="synStatement">is</span> <span class="synStatement">not</span> a valid DatetimeIndex <span class="synStatement">or</span> PeriodIndex
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># https://pandas.pydata.org/docs/reference/api/pandas.Series.dt.tz_localize.html</span>
df_datetime[<span class="synConstant">'datetime_utc'</span>] = df_datetime[<span class="synConstant">'datetime'</span>].dt.tz_localize(tz=<span class="synConstant">'UTC'</span>)
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime
<span class="synComment"># --------------------</span>
datetime val datetime_utc
<span class="synConstant">0</span> <span class="synConstant">2022</span>-<span class="synConstant">01</span>-<span class="synConstant">02</span> <span class="synConstant">03</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span> <span class="synConstant">10</span> <span class="synConstant">2022</span>-<span class="synConstant">01</span>-<span class="synConstant">02</span> <span class="synConstant">03</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span>+<span class="synConstant">00</span>:<span class="synConstant">00</span>
<span class="synConstant">1</span> <span class="synConstant">2022</span>-<span class="synConstant">02</span>-<span class="synConstant">03</span> <span class="synConstant">04</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span> <span class="synConstant">30</span> <span class="synConstant">2022</span>-<span class="synConstant">02</span>-<span class="synConstant">03</span> <span class="synConstant">04</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span>+<span class="synConstant">00</span>:<span class="synConstant">00</span>
<span class="synConstant">2</span> <span class="synConstant">2022</span>-<span class="synConstant">03</span>-<span class="synConstant">04</span> <span class="synConstant">05</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span> <span class="synConstant">20</span> <span class="synConstant">2022</span>-<span class="synConstant">03</span>-<span class="synConstant">04</span> <span class="synConstant">05</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span>+<span class="synConstant">00</span>:<span class="synConstant">00</span>
</pre>
<p>Q4. <code>Series.dt.tz_localize()</code>を使って時刻変換したけど、このdtって何?<br/>
A4. dtは時刻形式のSeriesに対するアクセサ(accessor)である。<br/>
Series.dt.xxx という形で、時刻情報の一部を抽出したり、今回のtz_localizeのように時刻関係のメソッドを使ったりできる。<br/>
Series.dt.xxx の一覧は <a href="https://pandas.pydata.org/docs/reference/series.html#datetimelike-properties">https://pandas.pydata.org/docs/reference/series.html#datetimelike-properties</a><br/>
dtについては <a href="https://pandas.pydata.org/docs/user_guide/basics.html#dt-accessor">https://pandas.pydata.org/docs/user_guide/basics.html#dt-accessor</a> を参照。</p>
<p>さて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/UTC">UTC</a>に設定したら希望の書式になってくれるかと思ったが、そうではなかった。
2022-01-02 03:00:00+00:00 という形式になってしまった。<br/>
2022-01-02T03:00:00Z という形式が欲しいんだけど。</p>
<p>Q5. 日付と時刻の間にあるTはどういう意味? 半角空白の場合と何が違うの?<br/>
A5. ISO 8601では日付と時刻の間にTという文字を書く必要がある。(半角空白にすることは認められていない)<br/>
Q6. 時刻の末尾にあるZはどういう意味? +00:00と何が違うの?<br/>
A6. Zと+00:00 はどちらもISO 8601で認められた表記法で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/UTC">UTC</a>であることを示す。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime.dtypes
<span class="synComment"># --------------------</span>
datetime datetime64[ns]
val int64
datetime_utc datetime64[ns, UTC]
dtype: <span class="synIdentifier">object</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># で、このままcsvに出力しても希望通りの形式にはならない。</span>
df_datetime.to_csv(<span class="synConstant">"temp1.csv"</span>)
<span class="synComment"># csvの中身を表示する</span>
! cat temp1.csv
<span class="synComment"># --------------------</span>
,datetime,val,datetime_utc
<span class="synConstant">0</span>,<span class="synConstant">2022</span>-<span class="synConstant">01</span>-<span class="synConstant">02</span> <span class="synConstant">03</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span>,<span class="synConstant">10</span>,<span class="synConstant">2022</span>-<span class="synConstant">01</span>-<span class="synConstant">02</span> <span class="synConstant">03</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span>+<span class="synConstant">00</span>:<span class="synConstant">00</span>
<span class="synConstant">1</span>,<span class="synConstant">2022</span>-<span class="synConstant">02</span>-<span class="synConstant">03</span> <span class="synConstant">04</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span>,<span class="synConstant">30</span>,<span class="synConstant">2022</span>-<span class="synConstant">02</span>-<span class="synConstant">03</span> <span class="synConstant">04</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span>+<span class="synConstant">00</span>:<span class="synConstant">00</span>
<span class="synConstant">2</span>,<span class="synConstant">2022</span>-<span class="synConstant">03</span>-<span class="synConstant">04</span> <span class="synConstant">05</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span>,<span class="synConstant">20</span>,<span class="synConstant">2022</span>-<span class="synConstant">03</span>-<span class="synConstant">04</span> <span class="synConstant">05</span>:<span class="synConstant">00</span>:<span class="synConstant">00</span>+<span class="synConstant">00</span>:<span class="synConstant">00</span>
</pre>
<h2 id="時刻が特定の書式になっているCSVを作る2つの方法">時刻が特定の書式になっている<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSV">CSV</a>を作る2つの方法</h2>
<p>3つの方法が考えられる。</p>
<ul>
<li>時刻のデータ(dtype <code>datetime64[ns, UTC]</code>)のまま、表示方法を変更する。</li>
<li>時刻のデータを<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>に保存する際に、時刻形式を変更する。</li>
<li>時刻のデータから、希望する形式の文字列に変換する。</li>
</ul>
<p>このうち2番目と3番目の方法は実現可能である。</p>
<p>Q7. 時刻のデータ(dtype <code>datetime64[ns, UTC]</code>)のまま、表示方法を変更する方法はあるのか?<br/>
A7. 多分ないと思う。あったら教えて下さい。</p>
<h3 id="時刻のデータをcsvに保存する際に時刻形式を変更する方法">時刻のデータを<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>に保存する際に、時刻形式を変更する方法</h3>
<p>Q8. 時刻のデータを<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>に保存する際に、時刻形式を変更する方法はあるのか?<br/>
A8. ある。to_<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>の引数にdate_formatを指定する。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># to_csvの引数にdate_formatを指定すると、csvに書き出すときに時刻を希望の書式にすることができる</span>
df_datetime.to_csv(<span class="synConstant">"temp2.csv"</span>, date_format=<span class="synConstant">"%Y/%m/%dT%H:%M:%SZ"</span>)
<span class="synComment"># csvの中身を表示する</span>
<span class="synComment"># date_format引数はdatetime,datetime_utc の両方の列に適用されている</span>
! cat temp2.csv
<span class="synComment"># --------------------</span>
,datetime,val,datetime_utc
<span class="synConstant">0</span>,<span class="synConstant">2022</span>/<span class="synConstant">01</span>/02T03:<span class="synConstant">00</span>:00Z,<span class="synConstant">10</span>,<span class="synConstant">2022</span>/<span class="synConstant">01</span>/02T03:<span class="synConstant">00</span>:00Z
<span class="synConstant">1</span>,<span class="synConstant">2022</span>/<span class="synConstant">02</span>/03T04:<span class="synConstant">00</span>:00Z,<span class="synConstant">30</span>,<span class="synConstant">2022</span>/<span class="synConstant">02</span>/03T04:<span class="synConstant">00</span>:00Z
<span class="synConstant">2</span>,<span class="synConstant">2022</span>/<span class="synConstant">03</span>/04T05:<span class="synConstant">00</span>:00Z,<span class="synConstant">20</span>,<span class="synConstant">2022</span>/<span class="synConstant">03</span>/04T05:<span class="synConstant">00</span>:00Z
</pre>
<h3 id="時刻のデータから希望する形式の文字列に変換する方法">時刻のデータから、希望する形式の文字列に変換する方法</h3>
<p>Q9. 時刻のデータを<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>に保存する際に、時刻形式を変更する方法はあるのか?<br/>
A9. ある。<code>Series.dt.strftime()</code> を使ってフォーマットを指定する。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Q10">Q10</a>. 出来上がったカラムのdtypeはどうなってるのか?<br/>
A10. 文字列、objectである。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime[<span class="synConstant">'datetime_utc'</span>].dt.strftime(<span class="synConstant">"%Y/%m/%dT%H:%M:%SZ"</span>)
<span class="synComment"># --------------------</span>
<span class="synConstant">0</span> <span class="synConstant">2022</span>/<span class="synConstant">01</span>/02T03:<span class="synConstant">00</span>:00Z
<span class="synConstant">1</span> <span class="synConstant">2022</span>/<span class="synConstant">02</span>/03T04:<span class="synConstant">00</span>:00Z
<span class="synConstant">2</span> <span class="synConstant">2022</span>/<span class="synConstant">03</span>/04T05:<span class="synConstant">00</span>:00Z
Name: datetime_utc, dtype: <span class="synIdentifier">object</span>
</pre>
<p>最初は訳わからなくてこれで作ってた。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime[<span class="synConstant">'datetime_utc'</span>].apply(<span class="synStatement">lambda</span> t: t.to_pydatetime().strftime(<span class="synConstant">"%Y/%m/%dT%H:%M:%SZ"</span>))
<span class="synComment"># --------------------</span>
<span class="synConstant">0</span> <span class="synConstant">2022</span>/<span class="synConstant">01</span>/02T03:<span class="synConstant">00</span>:00Z
<span class="synConstant">1</span> <span class="synConstant">2022</span>/<span class="synConstant">02</span>/03T04:<span class="synConstant">00</span>:00Z
<span class="synConstant">2</span> <span class="synConstant">2022</span>/<span class="synConstant">03</span>/04T05:<span class="synConstant">00</span>:00Z
Name: datetime_utc, dtype: <span class="synIdentifier">object</span>
</pre>
<p>一応、上のやり方を解説しておこう。<br/>
Seriesに対してapplyを使うので、tに該当するのは、 <code>datetime64[ns, UTC]</code> 型の1つの時刻である。<br/>
<code>to_pydatatime()</code>はPandasのTimestampオブジェクトを<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>のdatetimeオブジェクトに変換するもの。<br/>
<a href="https://pandas.pydata.org/docs/reference/api/pandas.Timestamp.to_pydatetime.html">https://pandas.pydata.org/docs/reference/api/pandas.Timestamp.to_pydatetime.html</a><br/>
で、datetimeオブジェクトに対して<code>strftime()</code>関数で文字列に変換している。</p>
<hr />
<p>以上、2つの方法で、YYYY-MM-DDThh:mm:ssZ という形式で時刻を出力することができた。</p>
<p>……これ実は、手動で「Z」という文字を付け加えているから、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>情報」としてZという文字を付加しているわけではない。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>を設定しなくても指定書式で<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>が作れるな。<br/>
まぁ、試行錯誤の結果ということで、このままにしておきます……。</p>
<hr />
<p>しかし今回調べてみると、
Series.dt.xxx でできることが意外と多かった。strftimeを使うと文字列に変換もできるのか。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>標準のdatetimeと対応関係を見てみよう。
例えば、df_datetime['datetime_<a class="keyword" href="http://d.hatena.ne.jp/keyword/utc">utc</a>'].dt.hourの場合。</p>
<pre class="code lang-python" data-lang="python" data-unlink>python_dt = datetime.datetime(<span class="synConstant">2022</span>, <span class="synConstant">1</span>, <span class="synConstant">2</span>, <span class="synConstant">3</span>, <span class="synConstant">0</span>)
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>python_dt.hour
<span class="synComment"># --------------------</span>
<span class="synConstant">3</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime[<span class="synConstant">'datetime_utc'</span>].dt.hour
<span class="synComment"># --------------------</span>
<span class="synConstant">0</span> <span class="synConstant">3</span>
<span class="synConstant">1</span> <span class="synConstant">4</span>
<span class="synConstant">2</span> <span class="synConstant">5</span>
Name: datetime_utc, dtype: int64
</pre>
<p>こう見ると、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>_dt」と「df_datetime['datetime_<a class="keyword" href="http://d.hatena.ne.jp/keyword/utc">utc</a>'].dt」が対応している。</p>
<p>次に、df_datetime['datetime_<a class="keyword" href="http://d.hatena.ne.jp/keyword/utc">utc</a>'].dt.strftime()の場合。</p>
<pre class="code lang-python" data-lang="python" data-unlink>python_dt.strftime(<span class="synConstant">"%Y/%m/%dT%H:%M:%SZ"</span>)
<span class="synComment"># --------------------</span>
<span class="synConstant">'2022/01/02T03:00:00Z'</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime[<span class="synConstant">'datetime_utc'</span>].dt.strftime(<span class="synConstant">"%Y/%m/%dT%H:%M:%SZ"</span>)
<span class="synComment"># --------------------</span>
<span class="synConstant">0</span> <span class="synConstant">2022</span>/<span class="synConstant">01</span>/02T03:<span class="synConstant">00</span>:00Z
<span class="synConstant">1</span> <span class="synConstant">2022</span>/<span class="synConstant">02</span>/03T04:<span class="synConstant">00</span>:00Z
<span class="synConstant">2</span> <span class="synConstant">2022</span>/<span class="synConstant">03</span>/04T05:<span class="synConstant">00</span>:00Z
Name: datetime_utc, dtype: <span class="synIdentifier">object</span>
</pre>
<p>これも、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>_dt」と「df_datetime['datetime_<a class="keyword" href="http://d.hatena.ne.jp/keyword/utc">utc</a>'].dt」が対応している。<br/>
Series.dtは単なるアクセサであるが、
「Series.dt は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>のdatetimeオブジェクトからなるSeriesのようなもの」と考えておくと、対応が分かりやすいのかもしれない……?<br/>
それでは。</p>
soratokimitonoaidani
Kivyを触ってみた
hatenablog://entry/13574176438058012168
2022-01-29T23:47:34+09:00
2022-01-30T00:05:10+09:00 触ってみたきっかけ Kivyって何 公式ドキュメント 環境 Kivyのインストール (Getting Started » Installing Kivy) インストールの次に見るべきページは何か? Create an application Pong Game Tutorial ボールを追加(Add the Ball) 触ってみたきっかけ GitHubの言語Pythonのトレンド の中にあったのでちょっと触ってみようと思った。 Kivyって何 Pythonの公式ドキュメント内のFAQの中のグラフィックユーザインターフェース FAQには、 Tkinter、Qtなどと並んでKivyの名前がある。こ…
<ul class="table-of-contents">
<li><a href="#触ってみたきっかけ">触ってみたきっかけ</a></li>
<li><a href="#Kivyって何">Kivyって何</a></li>
<li><a href="#公式ドキュメント">公式ドキュメント</a></li>
<li><a href="#環境">環境</a></li>
<li><a href="#Kivyのインストール-Getting-Started--Installing-Kivy">Kivyのインストール (Getting Started » Installing Kivy)</a></li>
<li><a href="#インストールの次に見るべきページは何か">インストールの次に見るべきページは何か?</a></li>
<li><a href="#Create-an-application">Create an application</a></li>
<li><a href="#Pong-Game-Tutorial">Pong Game Tutorial</a><ul>
<li><a href="#ボールを追加Add-the-Ball">ボールを追加(Add the Ball)</a></li>
</ul>
</li>
</ul>
<h2 id="触ってみたきっかけ">触ってみたきっかけ</h2>
<p><a href="https://github.com/trending/python">GitHubの言語Pythonのトレンド</a>
の中にあったのでちょっと触ってみようと思った。</p>
<h2 id="Kivyって何">Kivyって何</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>の公式ドキュメント内のFAQの中の<a href="https://docs.python.org/ja/3/faq/gui.html">グラフィックユーザインターフェース FAQ</a>には、
<a class="keyword" href="http://d.hatena.ne.jp/keyword/Tkinter">Tkinter</a>、Qtなどと並んでKivyの名前がある。これらは、パソコン上で<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>を作るためのライブラリらしい。</p>
<h2 id="公式ドキュメント">公式ドキュメント</h2>
<p><a href="https://kivy.org/doc/stable/">https://kivy.org/doc/stable/</a> :公式ドキュメント<br />
<a href="https://pyky.github.io/kivy-doc-ja/">https://pyky.github.io/kivy-doc-ja/</a> :公式ドキュメントを有志が日本語訳したもの (Kivyは2022年1月時点で2.0.0が最新である。日本語版は「2017年5月現在Kivy1.10に対応しております。」と書いてあり、情報が古いことには注意が必要。)</p>
<h2 id="環境">環境</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/MacBook%20Pro">MacBook Pro</a> (16-inch, 2019)<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/MacOS">MacOS</a> Catalina (10.15.7)</p>
<h2 id="Kivyのインストール-Getting-Started--Installing-Kivy">Kivyのインストール (Getting Started » Installing Kivy)</h2>
<p>公式ドキュメントの指示通りにインストールした。</p>
<pre class="code bash" data-lang="bash" data-unlink>% python3 -m venv kivy_venv
% source kivy_venv/bin/activate
(kivy_venv) % python --version
Python 3.8.5
(kivy_venv) % python3 --version
Python 3.8.5
(kivy_venv) % python -m pip install kivy[base] kivy_examples
zsh: no matches found: kivy[base]
(kivy_venv) % python -m pip install 'kivy[base]' kivy_examples
Collecting kivy[base]
……(以下略、インストール完了)</pre>
<p>一点詰まったのは、公式ドキュメントどおりに<code>python -m pip install kivy[base] kivy_examples</code>と実行してもエラーになってしまったことである。<br />
"<a class="keyword" href="http://d.hatena.ne.jp/keyword/zsh">zsh</a> no matches found kivy base"で検索して以下を発見。</p>
<p><a href="https://stackoverflow.com/questions/30539798/zsh-no-matches-found-requestssecurity">python - zsh: no matches found: requests[security] - Stack Overflow</a></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/zsh">zsh</a>では<code>[ ]</code>の記号が特別な意味(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>と同様の使い方)を持つため、このままだと実行に失敗する。<br />
特別扱いを避けて期待通りの動作にさせる方法はいくつかあるようだ。今回は、<code>kivy[base]</code>という文字列全体を引用符で囲むという方法を用いた。</p>
<p>インストール結果は以下のようになる。</p>
<pre class="code bash" data-lang="bash" data-unlink>(kivy_venv) % pip freeze
certifi==2021.10.8
charset-normalizer==2.0.9
docutils==0.18.1
idna==3.3
Kivy==2.0.0
Kivy-examples==2.0.0
Kivy-Garden==0.1.4
Pillow==9.0.0
Pygments==2.11.1
requests==2.26.0
urllib3==1.26.7</pre>
<p><code>python kivy_venv/share/kivy-examples/demo/showcase/main.py</code><br />
と打つと、デモ用のアプリが立ち上がる。画面を切り替えると、ボタンや<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%A7%A5%C3%A5%AF%A5%DC%A5%C3%A5%AF%A5%B9">チェックボックス</a>や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%EC%A5%B9%A5%D0%A1%BC">プログレスバー</a>など、いろいろな機能のデモができる。</p>
<h2 id="インストールの次に見るべきページは何か">インストールの次に見るべきページは何か?</h2>
<p>ここの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%B0%C0%FE">動線</a>がちょっと複雑。
公式ドキュメント上で「Installing Kivy」の次は以下のページである。
<a href="https://kivy.org/doc/stable/gettingstarted/first_app.html">https://kivy.org/doc/stable/gettingstarted/first_app.html</a><br />
でこのページにはだいたいこう書いてある:「Pong Game Tutorialがあるからそれをやってね。基本的なことは書いてあるから。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>に従うと、単純なアプリケーションを作るよ。Pong Game Tutorialはロードマップの中で一番重要な記事だよ」</p>
<p>「ロードマップ」という単語が突然登場したから「何かそういうまとめ画像(例えば<a href="https://roadmap.sh/backend">これ</a> みたいなやつ) があるの?」と思った。別にそういう「ロードマップ」はないらしい。</p>
<p>というわけで<a href="https://kivy.org/doc/stable/tutorials/pong.html">Pong Game Tutorial</a>に飛ぶと、以下のように書いてある。</p>
<p>Pong Gameの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>を始める前に</p>
<ul>
<li>Kivyがインストールされていることを確認してね</li>
<li>Kivyアプリケーションを実行する方法を確認してね。わからないなら、Create an application を見てね</li>
</ul>
<p>というわけで次に見るべきはCreate an applicationのようだ。</p>
<h2 id="Create-an-application">Create an application</h2>
<p><a href="https://kivy.org/doc/stable/guide/basic.html#quickstart">https://kivy.org/doc/stable/guide/basic.html#quickstart</a><br />
の'<a class="keyword" href="http://d.hatena.ne.jp/keyword/Hello%20World">Hello World</a>'アプリケーションを書き写して実行した。</p>
<h2 id="Pong-Game-Tutorial">Pong Game Tutorial</h2>
<p><a href="https://kivy.org/doc/stable/tutorials/pong.html">Pong Game Tutorial</a></p>
<p>拡張子kvのコードに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%F3%A5%BF%A5%C3%A5%AF%A5%B9">シンタックス</a>ハイライトが適用されなかったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/VSCode">VSCode</a>の以下をインストール。<br />
<a href="https://github.com/sspaink/kivy-vscode">https://github.com/sspaink/kivy-vscode</a></p>
<p>最初はコロンを使わずに間違ってイコールで書いてしまい、以下のエラーが出てきた。</p>
<pre class="code" data-lang="" data-unlink> ...
15: Label:
16: font_size: 70
>> 17: center_x = root.width * 3 / 4
18: top: root.top - 50
19: text: "0"
...
Invalid property name
center_x = root.width * 3 / 4</pre>
<p>次。<br />
ページにはこう書いてある。</p>
<blockquote><p>Note<br />
COMMON ERROR: The name of the kv file, e.g. pong.kv, must match the name of the app, e.g. PongApp (the part before the App ending).</p></blockquote>
<p>kvファイルの名前を間違えると動かないよ、という話だ。<br />
間違えるとどうなるんだ……? と思って、pong.kv を invalid_name.kv に名前変更して main.pyを実行した。
特にエラーは出なかった。<br />
しかし、その代わりに真っ黒な画面が出現した。<br />
……なるほど、ファイル名がpong.kvだから自動的に関連付けて読み込まれるけど、違う名前だと無関係なファイルだと思われて読み込まれないようだ。</p>
<h3 id="ボールを追加Add-the-Ball">ボールを追加(Add the Ball)</h3>
<p>ボールの位置を指定しているのは<code><PingGame></code>内部の<code>center: self.parent.center</code>のように見えたので、
<code>pong.kv</code>の7行目の <code>pos: self.pos</code>の必要性が無いように感じられた。これを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%E1%A5%F3%A5%C8%A5%A2%A5%A6%A5%C8">コメントアウト</a>して実行してみた。<br />
すると、ボールが画面の左下に表示された。……え、何でだろう。謎だわ。</p>
<hr />
<p><a href="https://kivy.org/doc/stable/tutorials/pong.html">Pong Game Tutorial</a><br />
の指示通りにコードを書いてPong(卓球)ゲームが完成するところまでやった。<br />
本当は各ファイルのそれぞれのコードがどう繋がって、実際のゲームができたのとかしっかり理解するのが良いんだろうけど、久々の技術ブログなのでこれくらいで切り上げておく。<br />
それでは。</p>
soratokimitonoaidani
ダンジョンエンカウンターズ プレイのメモ
hatenablog://entry/13574176438029737047
2021-11-06T12:47:26+09:00
2022-12-07T23:51:07+09:00 記述の基本方針 基本情報・前提条件? 18〜20時間 20〜22時間 22〜24時間 24〜26時間 26〜28時間 28〜30時間 30〜32時間 32〜34時間 34〜36時間 36〜38時間 38〜40時間 40〜42時間 42〜44時間 44〜46時間 46〜48時間 48〜50時間 50〜52時間 52〜54時間 54〜56時間 56〜58時間 58〜60時間 60〜62時間 62〜64時間 64〜66時間 66〜時間 www.jp.square-enix.com 記述の基本方針 2時間ごとに章を作る。 特にネタバレ配慮はしていないので注意してください。(プレイしたときのログというか…
<ul class="table-of-contents">
<li><a href="#記述の基本方針">記述の基本方針</a></li>
<li><a href="#基本情報前提条件">基本情報・前提条件?</a></li>
<li><a href="#1820時間">18〜20時間</a></li>
<li><a href="#2022時間">20〜22時間</a></li>
<li><a href="#2224時間">22〜24時間</a></li>
<li><a href="#2426時間">24〜26時間</a></li>
<li><a href="#2628時間">26〜28時間</a></li>
<li><a href="#2830時間">28〜30時間</a></li>
<li><a href="#3032時間">30〜32時間</a></li>
<li><a href="#3234時間">32〜34時間</a></li>
<li><a href="#3436時間">34〜36時間</a></li>
<li><a href="#3638時間">36〜38時間</a></li>
<li><a href="#3840時間">38〜40時間</a></li>
<li><a href="#4042時間">40〜42時間</a></li>
<li><a href="#4244時間">42〜44時間</a></li>
<li><a href="#4446時間">44〜46時間</a></li>
<li><a href="#4648時間">46〜48時間</a></li>
<li><a href="#4850時間">48〜50時間</a></li>
<li><a href="#5052時間">50〜52時間</a></li>
<li><a href="#5254時間">52〜54時間</a></li>
<li><a href="#5456時間">54〜56時間</a></li>
<li><a href="#5658時間">56〜58時間</a></li>
<li><a href="#5860時間">58〜60時間</a></li>
<li><a href="#6062時間">60〜62時間</a></li>
<li><a href="#6264時間">62〜64時間</a></li>
<li><a href="#6466時間">64〜66時間</a></li>
<li><a href="#66時間">66〜時間</a></li>
</ul>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.jp.square-enix.com%2Fde%2F" title="DUNGEON ENCOUNTERS | SQUARE ENIX" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.jp.square-enix.com/de/">www.jp.square-enix.com</a></cite></p>
<h2 id="記述の基本方針">記述の基本方針</h2>
<ul>
<li>2時間ごとに章を作る。</li>
<li>特にネタバレ配慮はしていないので注意してください。(プレイしたときのログというかメモという感覚で書いている)</li>
</ul>
<h2 id="基本情報前提条件">基本情報・前提条件?</h2>
<ul>
<li>Switch版を買いました</li>
<li>一回「これは仮だから」といいつつ8時間プレイして、セーブデータを消して新しく1からやり直した</li>
</ul>
<p>まぁ割と安全めに倒した動きをしていると思います。
* 全滅したら救出しなきゃいけない→全滅しても良いように、たくさんのキャラを育てておく</p>
<h2 id="1820時間">18〜20時間</h2>
<p>えーー全滅しました。2回目。<br/>
33階。敵は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%EC%A5%F3%A5%C8">トレント</a>とヘルプランツで合計4体くらいだったと思う。 また魔法攻撃ばっかりされて死んだパターン。</p>
<p>手持ちのレベルを上げて救出しに行くかと思ったけど、このゲームはレベルを上げると直接強くなるというものではない。(HPが上がるけどその効果は微々たるものだ)。
強くなるためには、以下のどちらかをする必要がある。</p>
<ul>
<li>レベルが上がる→装備ポイントが上がる→今までできなかった強い装備ができるようになる</li>
<li>新しい敵を倒す→店に新しい武器防具が並ぶ→それを買う→ステータスが上がる</li>
</ul>
<p>1点目について。装備ポイントはとっくに十分上がっていて、「今までできなかった装備」はほとんど無いと思っている。<br/>
2点目について。全滅したメンバーも全員、ブロンズアーマー(1950)を装備していた。店にはそれより上の防具がない。いや、羽付き帽子(2100)はあるけど……この魔法防御の150の違いは誤差だろう。もっと強い防具を買わせろ……。
というわけで、レベルを上げても強くなれそうにない。これでは確実に救出できる自信がない。どうしろというんだろう。
アンクを32階で取ってたのが幸いで、これでアンクをアカデミーにおいておけば、救出して即0階に戻れる。</p>
<p>20時間:忘れた</p>
<h2 id="2022時間">20〜22時間</h2>
<p>全滅部隊の救出は完了。淡々とレベル上げ。</p>
<p>22時間:35階まで、完全踏破25階</p>
<h2 id="2224時間">22〜24時間</h2>
<ul>
<li>36階で初めての石化。「石化中」から時間が経つと石化になると思ってたけど、敵によっては「石化中」を経由せずにいきなり石化になるパターンもあるっぽい。</li>
<li>石化解除を踏んでおいたおかげで、直近の場所がわかってよかった。31階の右下にある。</li>
<li>防具、ブロンズヘルムとラメラーアーマーが並び始めた</li>
<li>37階で地図問題5の答え 似たような箇所がたくさんある引っかけ問題。</li>
<li>35階で仮想エレベーター上がりを獲得。</li>
<li>37階は武器防具の店だけあって回復系マスがない。新しいパターンだ……</li>
<li>37階で即死攻撃を喰らってHP回復アビリティ回数が尽きたので、武器防具を買い込んでから33階まで戻る。
<ul>
<li>マリアル7、マランダオール4、ラメラーアーマー、アーバレスト</li>
</ul>
</li>
<li>次に進むときは39階から0階に戻りたいな(どうせワープポイントあるでしょ?)</li>
</ul>
<p>24時間:38階まで、完全踏破25階、最高レベル45</p>
<h2 id="2426時間">24〜26時間</h2>
<ul>
<li>39階まで行って帰還成功。</li>
<li>40階チラ見。30階に初めて行ったときは結構キツそうな印象だったけど、それと違って行けそうだ感がある。</li>
<li>39階にアクセサリー店も並んでいるので、今後必要になったら39階にワープしてここに行けば良し。</li>
<li>39階のデッドゲートに1人飛ばされる。行方不明になるのね。</li>
<li>上位8人のうち、1人は石化→回復させたけど回収せず放置、1人は飛ばされて行方不明。……少し危ないから回収するか。</li>
<li>犬のフラウを27階に行って犬のフラウを回収。</li>
<li>36階で石化してた1人を回収。</li>
<li>そのままうろついてたら、36階の右下部分に各種回復があるじゃん!遠かったから気づかなかった。まぁそれ狙いでわざと外れた位置に配置してるんだろうけど。</li>
<li>武器はアーバレストと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%EA%A5%CF%A5%EB%A5%B3%A5%F3">オリハルコン</a>がメインになった。</li>
</ul>
<p>26時間:40階まで、完全踏破27階、最高レベル48</p>
<h2 id="2628時間">26〜28時間</h2>
<p><strong>全滅しました。</strong>3回目。 <br/>
41階。サムライとかいう敵がHP直接攻撃を繰り返してきた。<br/>
1人が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%F3%A5%A4%A1%BC%A5%BF%A1%BC">マンイーター</a>に食われて、「行けるかな」と思ってそのまま進んでたらあえなく全滅。行けるかな、じゃねぇんだよ。</p>
<ul>
<li>もう1人、38階でデッドゲートに飛ばされる。</li>
<li>レベルの高い順にトップ9人のうち、3人が41階で戦闘<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%D4%C7%BD">不能</a>。1人が40階で食べられ。2人が38階と39階で飛ばされて行方不明。無事なのが3人。</li>
<li>あれ、これかなりヤバくない?</li>
<li>武器は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B1%A5%F3%A5%BF%A5%A6%A5%ED%A5%B9">ケンタウロス</a>の弓矢と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%EA%A5%CF%A5%EB%A5%B3%A5%F3">オリハルコン</a>がメインになった。</li>
</ul>
<p>28時間:42階まで、完全踏破30階、最高レベル50</p>
<h2 id="2830時間">28〜30時間</h2>
<ul>
<li>飛ばしと石化を無効化して39階へ。</li>
<li>2人が38階と39階で飛ばされて行方不明だったのを回収した。(飛ばされたときと同じフロアのランダムなマスに行く仕様だと思う。)</li>
<li>38、21、22階を踏破。アビリティのポイントが必要なので。</li>
<li>17、16、15階を踏破。アビリティのポイントが必要なので。</li>
<li>ふと15階を見ると地図問題2の答えだったので、アイテムを取得。</li>
<li>4人パー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%A3%A1%BC">ティー</a>で41階は行けた。けど、3人で行くとそこまでに全滅しそうで心配。</li>
<li>そのまま降りていったら44階で戦闘<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%D4%C7%BD">不能</a>回復・HP回復は見つけた。</li>
<li>レベルの高い順にトップ9人のうち、3人が41階にいる(戦闘<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%D4%C7%BD">不能</a>からは回復)。1人が40階にいる(食べられからは回復)。動かせるのが5人。</li>
</ul>
<p>30時間:44階まで、完全踏破37階、最高レベル52</p>
<h2 id="3032時間">30〜32時間</h2>
<ul>
<li>ロリカセグメンタタとかいう舌を噛みそうな名前の防具を買って、39階から再出発。</li>
<li>42階でトレジャー6。パウ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A1%BC%A5%D6%A5%E9">ダーブラ</a>スター。あんま使えなさそう……</li>
<li>44階、一方通行の転移装置を始めて見た。92階に飛ばすやつ。なんか92階がひどいって<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>でちょっと見たんだよな……これか……もちろん踏まない。</li>
<li>46→47→48階、一方通行の階段。そのまま無理やり行ったら49階まで行けるんじゃね? と思ったが、安全第一で44階まで戻る。</li>
<li>でも44階にはアビリティ回数回復がない……</li>
<li>新武器が来た。
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%EB%A5%BB%A5%A6%A5%B9">ペルセウス</a>の弓矢 ← インプ ← 71、73 ← 44〜46階</li>
<li>ローリングエン ← ス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B1%A5%EB%A5%C8">ケルト</a>ン ← 6F、71 ← 44〜45階</li>
</ul>
</li>
<li>44〜46階をウロウロ。</li>
<li>46階で初:モルモット。
<ul>
<li>説明には「攻撃が失敗しやすくなる状態」と書いてあって、「たまに失敗するのかな」と思ったら、基本的に失敗である。ひどい。</li>
<li>試しに記録を取ってみたら、15回連続で失敗して16回目に攻撃成功した。おそらく攻撃成功率は5%〜10%だと思われる。</li>
<li>解除方法は不明なので放置……</li>
</ul>
</li>
<li>防具、アーメットとバルビュータが同時に入荷されてた。防具が一気に2段階上がるのは初めてだな…… あとはシルバーアーマーも入荷されてた。</li>
<li>モルモットと化したナンガパルをアカデミーに預ける。あと40〜41階の4人を回収。</li>
<li>レベルの高い順にトップ9人のうち、1人モルモット。</li>
</ul>
<p>32時間:48階まで、完全踏破39階、最高レベル57</p>
<h2 id="3234時間">32〜34時間</h2>
<ul>
<li>余計な戦闘をせず、49階まで行って戻ってこよう。</li>
<li>39階に飛んですぐに仮想エレベーターで降りる。46階から49階まで行って帰還成功。
<ul>
<li>この瞬間が一番ホッとするね。</li>
</ul>
</li>
<li>48階トレジャー7。ただの4800G。しょぼい。</li>
<li>50階。噂に聞いた、金を取られる床か。きっと、1マス600Gか800Gくらいだろ? 試しに乗ってみるか。「11100G」え? は????</li>
<li>39階で83のマスを倒す→新しい武器 <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%E5%A5%E9%A5%F3%A5%C0%A5%EB">デュランダル</a> が店に並んでるじゃん→83くらいのマスは(連続じゃなくて)一発なら倒せる。ちょっと下に潜って倒して強い武器を手に入れよう。</li>
<li>54階、トレジャー9。攻撃速度アップね。</li>
<li>55階に降りて進みだしたらいきなり落とし穴に落ちた。68階に行った。慌ててアンクで戻った。</li>
<li>47階で「落とし穴発見」を見つけた。</li>
<li>39階、地図問題7の答え。</li>
<li>レベルの高い順にトップ9人のうち、1人モルモット。</li>
</ul>
<p>34時間:54階まで、完全踏破39階、最高レベル59</p>
<h2 id="3436時間">34〜36時間</h2>
<ul>
<li>52階のバトルで全滅しそうになってギリギリ勝つ。危ない。</li>
<li>あちこち行ってるので武器防具の個数が揃わない。まとめるか。</li>
<li>武器
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B0%A5%E9%A5%C7%A5%A3%A5%A6%A5%B9">グラディウス</a></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%E5%A5%E9%A5%F3%A5%C0%A5%EB">デュランダル</a> ← 鎧の男 ← 83、86 ← 52階近辺(39階にも少なからず83がいる。こっちのほうが便利かも)</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%EA%A5%B9%A5%BF">バリスタ</a> ← <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AC%A1%BC%A5%B4%A5%A4%A5%EB">ガーゴイル</a> ← 7E、81 ← 50階近辺</li>
</ul>
</li>
<li>防具
<ul>
<li>アーメット ← <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A6%A5%A7%A5%A2%A5%A6%A5%EB%A5%D5">ウェアウルフ</a> ← 6A、6C ← --階近辺</li>
<li>バルビュータ ← ブラックベア ← 76、78 ← 46〜48階</li>
<li>シルバーアーマー ← <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%D2%A1%BC%A5%E2%A5%B9">ベヒーモス</a> ← 76、79 ← 46〜48階</li>
</ul>
</li>
<li>アクセサリー
<ul>
<li>コンドライト ← ジェネライザー ← 82〜86 ← 52階近辺</li>
</ul>
</li>
<li>「不明者発見」の値を見ながら52階をウロウロしてたら不明者発見。52, 68, 39 ントレヤナ。</li>
<li>53階、地図問題8の答え。……専用装備だな。</li>
</ul>
<p><strong>全滅しました。</strong>4回目。 <br/>
56階。8Bだとおもう、ウィザードと死のカードとラバー。魔法攻撃ばっかりされて死んだパターン。<br/>
結構深く潜っちゃって、大丈夫か微妙なところで「有料床回避」が見えて、1回バトルに勝てば到達できるから、これだけ取って帰ろう……と思ったけど帰れなかった。</p>
<p>36時間:56階まで、完全踏破41階、最高レベル59</p>
<ul>
<li>レベルの高い順にトップ9人のうち、4人戦闘<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%D4%C7%BD">不能</a>(56階)、1人モルモット。</li>
</ul>
<h2 id="3638時間">36〜38時間</h2>
<ul>
<li>49階をウロウロしてたら不明者発見。謎の掃除ロボじゃん! 49, 34, 88 K2000。連れて帰る。</li>
<li>52, 68, 39 ントレヤナを連れて帰る。</li>
<li>K2000に「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B0%A5%E9%A5%D5%A5%A7%A5%F3">グラフェン</a>加工」を装備させるとものすごい耐久力になるな。武器も片方を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%BC%EA">素手</a>にしたけど、ゾンビ系を一撃で殺せるので悪くない。</li>
</ul>
<p>38時間:57階まで、完全踏破41階、最高レベル64</p>
<h2 id="3840時間">38〜40時間</h2>
<ul>
<li>よし、そろそろ56階の戦闘<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%D4%C7%BD">不能</a>4人を連れて帰ろう。ついでに「有料床回避」も取ってこよう。</li>
<li>仮想エレベーターでどこに移動するか調査。
<ul>
<li>0E転送→49階→仮想エレベーター下り→50階→仮想エレベーター下り→54階</li>
<li>0E転送→49階→03のマス→仮想エレベーター下り→66階</li>
<li>0E転送→49階→03の上のマス→仮想エレベーター下り→59階</li>
<li>0E転送→49階→01のマスから50階に移動→仮想エレベーター下り→59階</li>
<li>0E転送→49階→01のマスから50階に移動→1マス上に移動→仮想エレベーター下り→99階(!?)</li>
<li>0E転送→49階→01のマスから50階に移動→1マス下に移動→仮想エレベーター下り→66階</li>
<li>0E転送→49階→一番上まで移動→仮想エレベーター下り→61階</li>
</ul>
</li>
<li>上の検証をしてて59階で「精神統一」が取れた。なんて都合の良いアビリティなんだ。ただしコストは非常に高い。35もするのかよ。</li>
<li>「さぁ帰ろう」と思ったらアンクを実行してなかった。しかも59階の転送装置までは辿り着けそうにない。死ぬかと思った。なんとか49階まで上がって戻ってこられた。</li>
<li>56階の「有料床回避」は、下側からは入れない。上から「ナイトムーブ」で飛んでくる必要がある。</li>
<li>56階で敵6人と戦って死にそうになる。敵の数は1〜6からランダムだと思うけど、最大数の6体出てくると結構きついな。</li>
<li>59階から帰還成功。
<ul>
<li>冷静によく見たらムーブで店にジャンプできる距離だった。隠し床で敵と戦う必要はなかった。</li>
</ul>
</li>
<li>幻城とは何。何で俺は城と戦ってるの。</li>
<li>60階以降……クソだるい……床が見えない……</li>
</ul>
<p>40時間:60階まで、完全踏破41階、最高レベル65
* レベルの高い順にトップ11人(K2000とントレヤナのぶんだけ増えた)のうち、1人モルモット。</p>
<h2 id="4042時間">40〜42時間</h2>
<ul>
<li>56・57・59・61階をチマチマやって完全踏破。</li>
</ul>
<p>42時間:63階まで、完全踏破45階、最高レベル66</p>
<ul>
<li>レベルの高い順にトップ11人のうち、1人モルモット。</li>
</ul>
<h2 id="4244時間">42〜44時間</h2>
<ul>
<li>63階、HP全回復・全を入手。</li>
<li>数値問題1と4を解く。</li>
<li>ついでに35階を踏破。</li>
<li>行方不明者が35±4, 42, 75 だなと分かったので仮想エレベーターで下に。39, 42, 75 でモデナリを回収(ホクガクじゃないのか……)。</li>
<li>49階をウロウロしていたら、行方不明者が49±15, 35, 84 だなと分かったので仮想エレベーターで上に。34, 42, 75でホクガクを回収。</li>
<li>……ところでこの2人は行方不明時のレベルとフロアが一緒なんですが、もしかしてそういう法則があったりするか? だとするとレベル60のネコは60階にいるのか?</li>
<li>60±2, 41, 41 に1人、その近くにもう1人……なんじゃこりゃ。</li>
<li>61, 45, 50がオウユー。
<ul>
<li>61階でレベル61。</li>
</ul>
</li>
<li>58, 41, 41 ネコ。59階でうろついてから1つ上に上がると楽。
<ul>
<li>60階じゃないじゃん。ネコは例外か?</li>
</ul>
</li>
</ul>
<p>というわけで一気に4人(モデナリ・ホクガク・オウユー・ネコ)回収完了。</p>
<p>44時間:65階まで、完全踏破46階、最高レベル67</p>
<h2 id="4446時間">44〜46時間</h2>
<ul>
<li>レベル43のジョラスはどうせ43階やろ。行こう。回収成功。</li>
<li>回収する前の戦闘で、ホクガクがモルモットになりやがった……なんか強いらしいのに……悲しみ……</li>
<li>43階踏破したけど、ここ専用装備や特殊装備を売るショップがあるのね。</li>
<li>64階、トレジャー10、ただの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%EC%A5%C3%A5%C9%A5%CE%A1%BC%A5%C8">ドレッドノート</a>やんけ、つまらん。</li>
<li>65階で迷ったので、調べておいたこれで66階に行って探検。この辺の敵がギリギリ倒せるくらいだ。
<ul>
<li>0E転送→49階→03のマス→仮想エレベーター下り→66階</li>
</ul>
</li>
<li>さて59階から降りるとどこに行くかは調べておこう。
<ul>
<li>0F転送→59階→仮想エレベーター下り→60階→仮想エレベーター下り→68階</li>
<li>0F転送→59階→14のマス→仮想エレベーター下り→60階→仮想エレベーター下り→62階</li>
<li>0F転送→59階→15のマス→仮想エレベーター下り→62階→仮想エレベーター下り→66階</li>
<li>0F転送→59階→16のマス→仮想エレベーター下り→63階→仮想エレベーター下り→78階</li>
<li>0F転送→59階→17のマス→仮想エレベーター下り→63階→仮想エレベーター下り→67階</li>
</ul>
</li>
<li>ネコのナイフ&フォークが強いという話。</li>
</ul>
<p>46時間:69階まで、完全踏破47階、最高レベル68</p>
<h2 id="4648時間">46〜48時間</h2>
<ul>
<li>69階から戻ってくる。</li>
<li>66階でネコがモルモットになったんだけどー。しかも同時にロボが食べられたんだけどー。</li>
<li>モルモットの解除方法、未だに不明。
<ul>
<li>解除マスがどこかにあるということは分かっているけど。イベントブックに書いてあるから。でも見たことはないね。</li>
</ul>
</li>
<li>69階の普通には到達できないところに「透明床が見える」アビリティがあるね……どうやるんだ
<ul>
<li>ランダムジャンプを繰り返して、行けることを願う</li>
<li>座標を覚えておいて、上か下から仮想エレベーターで移動する</li>
<li>正攻法でどう行けば良いのかよく分からん。それを探して66階まで行ったらこのザマだよ。</li>
</ul>
</li>
<li>トレジャーリセット(FC)を初めて倒した。
<ul>
<li>これくらいまでキャラが育ってれば、攻撃を受ける前に倒すこともできるな。</li>
</ul>
</li>
<li>「透明床発見」を取りに行こう。
<ul>
<li>69階、南は50〜51、東は42〜45。特に51, 42が7Fマス、51、45が02マス。を調べる。</li>
<li>59階へ。え、51, 42のマスがあるじゃん。</li>
<li>そこから仮想エレベーターで63階→69階に行って、「透明床発見」を入手。</li>
</ul>
</li>
<li>透明床発見を装備して、そのまま69、68、67階を完全踏破。いやこれ
があると100倍楽だな。</li>
</ul>
<p>48時間:70階まで、完全踏破51階、最高レベル69</p>
<ul>
<li>2人がダンジョン内、そして3人がモルモット。特にネコとホクガクは早くモルモットを治して使いたいんだが〜〜……</li>
</ul>
<h2 id="4850時間">48〜50時間</h2>
<ul>
<li>強めの編成にして階数を進めに行こう。</li>
<li>HP満タンで攻撃力倍を初めて着けたら、めちゃ強い。どんどん倒せる。</li>
<li>72階の途中で落とし穴で進めず、面倒になったので、仮想エレベーター下りを実行。84階へ。</li>
<li>倒せそうな気がしたので1回だけ戦闘してみる。やっぱり倒せた。</li>
<li>適当に仮想エレベーター上りを実行したら、79階に着いて、そこから転送装置を見つけて帰ってきてしまった。マジかよ。</li>
<li>81階をウロウロしてたらやたらとトレジャーリセットに出会った。……もしかして、トレジャーリセットってトレジャーがある階層のみに出現する法則とかあるのか?</li>
<li>50, 51, 52階を踏破。(50〜59階は、落とし穴見える + 有料床回避 + 透明床見える を付ける必要があるので、なかなか厄介だね)</li>
<li>52階に謎の液体を売る店があったのに初めて気づいた。</li>
<li>そのまま53, 54, 55階を踏破。</li>
<li>仮想エレベーターで遊んでいたら4階から一気に91階に着いた。なにこれ怖い。</li>
<li>91階にトレジャーがいくつかあり、拾ったらイベントブック上の位置が上書きされた。なにこれ怖い。</li>
</ul>
<p>50時間:81階まで、完全踏破57階、最高レベル76</p>
<h2 id="5052時間">50〜52時間</h2>
<ul>
<li>80, 81階を完全踏破。</li>
</ul>
<p><strong>全滅しました(行方不明)。</strong>5回目。 <br/>
74階の完全踏破を狙ってたけど、最後1マスが落とし穴だったんだよね。まぁ大丈夫でしょって言って落ちてみたらこのザマである(永遠に落ち続けて行方不明になった)。そして落とし穴のマスは踏破にカウントされない……マジかよ。</p>
<ul>
<li>急いで69階のK2000を回収する。</li>
<li>81階トレジャーでモルモットソードなるものを見つけたので、モルモット状態のネコに装備する。大ダメージが出せた。それは良いけど、モルモットが治らない。</li>
<li>ダメージは固定値で287496。……何だこの半端な値は。数字6桁を見たらマス目だと思え、でいいのだろうか。</li>
<li>28, 74, 96というマスは存在しない。</li>
<li>69, 47, 82のマスはあるけど特に何も起きなかった。</li>
<li>70階71階を完全踏破。</li>
<li>行方不明4人とモルモット3人を除外すると、使えるキャラが少ないので、次に全滅するとヤバい。だいぶヤバい。</li>
<li>万が一に備えてジョラスをレベル43→51まで育成。</li>
</ul>
<p>52時間:84階まで、完全踏破61階、最高レベル80</p>
<h2 id="5254時間">52〜54時間</h2>
<ul>
<li>68階のルエンゾを回収する。</li>
<li>行方不明4人、モルモット3人、今使えるレベル60以上は7人。7人のうち<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B2%A5%A4%A5%B7">ゲイシ</a>ャブランとントレヤナはステータス低いから育成したくないんだよなぁ。</li>
<li>80階にどうせドラゴンがいるんでしょ、レベル80なんだから……見つけた。80, 42, 45で、あれ? 行方不明になってたシュローツェだった。</li>
<li>80±1, 62, 76 に誰かいることを突き止めて79階へ。行方不明になってたフラウだった。</li>
<li>今使えるレベル60以上は9人。これならまぁ安心。</li>
<li>K2000(ロボ)のEPを上げて、高<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%CA%A5%B8%A1%BC">エナジー</a>ミサイルを装備可能にした。こいつ、いわゆるぶっ壊れ性能してるな。</li>
<li>85階で落とし穴を見た。この(80〜89階)地帯にも落とし穴ってあるんだ……。</li>
<li>86階でテレポーテーションを手に入れた。「床が無い場合は失敗となりパー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%A3%A1%BC">ティー</a>メンバー全員がバラバラに飛ばされます」割と怖いこと書いてあるな……</li>
<li>テレポーテーションがあった座標はイベントブックで見られるから、そこを指定して86階からスタートできるのね。</li>
<li>あとはレア系のショップにもすぐ行ける。というわけで謎の液体の店にワープして買い込んできた。</li>
<li>しかしテレポーテーションのコストが高いから、アビリティポイントを増やしておきたい。</li>
<li>63階・62階を踏破。</li>
</ul>
<p>54時間:86階まで、完全踏破64階、最高レベル80</p>
<h2 id="5456時間">54〜56時間</h2>
<ul>
<li>しかしここから先をどう進めば良いんだろう。武器はずっとサジタリウスの弓矢で固定で、それより強いのは落ちてこないし。</li>
<li>万が一に備えてモデナリ(レベル47)を連れて、踏破階数を増やしに。64階を踏破。</li>
<li>65階で地図問題の答えに気づいた。ネコ音波。しかしいまネコはモルモット状態で使えないのや……</li>
<li>65階を踏破。モデナリも52まで育ちました。</li>
<li>この辺にドラゴンいるんでしょ……と言いつつ81階を探索していたら、行方不明だったオウユーを発見。</li>
<li>もう4人パー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%A3%A1%BC">ティー</a>でも、アンクで0階に戻る→パー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%A3%A1%BC">ティー</a>人数減らしてテレポーテーション→回収して戻る になるからかなり楽だね。</li>
<li>86階から進んでみるも、88階あたりで限界を感じる。戦闘をいくつも重ねるのが難しい。</li>
<li>91階で1回か2回戦闘するだけなら倒せるんじゃないの? と、やってみる。
<ul>
<li>K2000の面目躍如。高<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%CA%A5%B8%A1%BC">エナジー</a>ミサイルが強すぎる。</li>
<li>ここでガストラフェテスを敵が落としていった! 別格最強武器やん。</li>
</ul>
</li>
</ul>
<p>56時間:88階まで、完全踏破66階、最高レベル86</p>
<h2 id="5658時間">56〜58時間</h2>
<ul>
<li>88階から仮想階段で89階に降りる。
<ul>
<li>仮想エレベーターで下に床が無かったときの挙動ってどうなるんだろう 落ち続けて行方不明になるのか?</li>
<li>→「床はない」と出て移動しないだけになる。良かった</li>
</ul>
</li>
<li>89階から帰還成功。</li>
<li>そしてFFマスを見つけた。(これ99階にあるのかと思ったら89階にあるのか……!)</li>
<li>ここより手前で十分強化してから挑んだほうが良いんだろうなぁ。</li>
<li>82階を踏破。</li>
<li><strong>全滅しました(行方不明)。</strong>6回目。
<ul>
<li>87階あたりで、行方不明者までのマス数を見ながら歩いてたら落とし穴(見えてた)に落ちた。マジかよ。</li>
</ul>
</li>
<li>行方不明者までのマス数で混乱しないように、最初の方の行方不明者を回収しとくか。</li>
<li>16, 29, 33 のイルベルトを回収。ついでに2階にずっといたロードピークを回収。</li>
<li>39階で銃を買うついでに行方不明者の位置を特定。 39+44, 73, 37 ラウラギ。(5回目で落とし穴に落ちた人)</li>
<li>行方不明者は(6回目で)落とし穴に落ちた4人と、バルトロと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%D0">エバ</a>レスの6人。</li>
<li>モデナリ(レベル52)を連れつつ行方不明者を探して回ることにする。</li>
<li>57〜59階が割と広範囲にマス目が分布している・移動しやすい。このへんを歩きながら行方不明者までの距離を見て、95階にオウユーがいることを特定。</li>
<li>95階にアイテム「ゲーム」を売る店がある……なんじゃこりゃ。</li>
<li>99, 58, 36 エルバ を発見、回収。91階にフラウを発見、回収。</li>
<li>再び59階へ。</li>
<li>91階でルエンゾを発見。</li>
<li>行方不明者の状況は以下の通り。
<ul>
<li>(6回目で)落とし穴に落ちた4人のうち2人回収完了。95階オウユーと91階ルエンゾは発見済みで未回収。</li>
<li>78階でバルトロが石化してる、発見まで完了</li>
<li>最後の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%D0">エバ</a>レスは「行方不明」だけどレーダーに探知されないみたいね。どうなってるんだ。</li>
</ul>
</li>
<li>一方通行式転送装置の2と3を見つけた。これ何の意味があるの?</li>
</ul>
<p>58時間:89階まで、完全踏破67階、最高レベル87</p>
<h2 id="5860時間">58〜60時間</h2>
<ul>
<li>90階、ちょっと様子を見てみるか……絶対ボスを倒さなきゃいけないってことは、一本道の途中にいるみたいな形かな?</li>
<li>90階は変な形状のマス目配置をしている。</li>
<li>敵と戦わないように歩いていたつもりが、気づかないうちにFEマスを踏んだらしい。</li>
<li>傀儡の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%D0">エバ</a>レス→パノプティコアに勝利。スタッフロールが流れた。すごい呆気ないというか拍子抜けというか。ガストラフェテスもアドレス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D6%A5%EC%A5%A4%A5%C9">ブレイド</a>も装備してなかったし、他の装備も適当だったのに。</li>
<li>90階以降のマスが視認しにくいのが全部悪い。</li>
<li>73階を踏破。</li>
</ul>
<p>60時間:</p>
<h2 id="6062時間">60〜62時間</h2>
<ul>
<li>(6回目で)落とし穴に落ちた4人のうち、残してた95階オウユーと91階ルエンゾを回収。</li>
<li><strong>全滅しました。</strong>7回目。
<ul>
<li>97階も戦闘1回くらいだったら行けるかなーと(一方通行式転送装置のマスにテレポーテーションして)F4マスを踏んだら<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%C6%A5%EB%A5%AE%A5%A6%A5%B9">ベテルギウス</a>×5が出てきて一気に死んだ。あんなん勝てるの?</li>
</ul>
</li>
<li>この場合は、再度テレポーテーションして、やられたマスに移動して、キャラを回収すればよい。簡単に4人とも回収できた。</li>
<li>87階を踏破。</li>
<li>88階、やたらとモンスターのマスが多くないか?</li>
<li>78階を踏破、バルトロを回収。</li>
<li>74, 75, 76階を踏破。</li>
</ul>
<p>58時間:95階まで、完全踏破76階、最高レベル92</p>
<h2 id="6264時間">62〜64時間</h2>
<ul>
<li>久しぶり(今日は2022年1月30日)過ぎて状況を覚えてない……</li>
<li>メンバー転送を持ってないからいちいち厄介なのよね。70階台にあるってブログを見た気がする。残りは72階か。</li>
<li>72階でメンバー転送を取得。そして完全踏破。</li>
<li>24〜26階をまだ踏破してなかったので完全踏破。</li>
<li>91階をウロウロしてるけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E1%A5%EA%A5%E5%A5%B8%A1%BC%A5%CC">メリュジーヌ</a>が出現するマスが多くてうかつに戦闘できない。</li>
<li>287496 = 66 ^ 3 らしい。けど66, 66, 66というマスは無い。どうしろと?</li>
</ul>
<p>64時間:95階まで、完全踏80階、最高レベル94</p>
<ul>
<li>モルモットを治す方法が分からんので考える。</li>
<li>45階にテレポーテーションする。</li>
<li>モルモットソードの与えるダメージが300763に変わった。何で? と思ったら300763 = 67 ^ 3である。</li>
<li>「モルモットソードを装備した人のレベルの3乗」が与えるダメージになるんだろう。</li>
<li>あり得るとしたら魔法反射をつけて→<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E1%A5%EA%A5%E5%A5%B8%A1%BC%A5%CC">メリュジーヌ</a>が呪文を唱えたら反射する? かなぁ。と思ったけど、違うようだ。</li>
<li>分からんのでネタバレを見た。</li>
<li><a href="https://twitter.com/kiryuda/status/1451923841740013568">https://twitter.com/kiryuda/status/1451923841740013568</a></li>
<li>一度わかればあとは簡単、モルモットの4人の治癒が完了した。</li>
<li>91〜95階あたりならまぁ戦えるようになってきた。が、なかなかアイテムは落ちない。</li>
<li>91階、95階を完全踏破。</li>
<li>88階も踏破……しようとしたけど敵が多くて鬱陶しい……</li>
<li>レベル66のネコを連れて行って、これを育てよう。</li>
</ul>
<h2 id="6466時間">64〜66時間</h2>
<hr />
<ul>
<li>武器(物理ダメージ)
<ul>
<li>最強1つ手前
<ul>
<li>単体固定ダメージ:カラドボルグ ← <a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%B4%B5%F0%BF%CD">鉄巨人</a> ← C6、C8 ← 〜階</li>
<li>全体固定ダメージ:リグナムシャフト ← BF、C1 ←</li>
<li>単体ランダムダメージ:</li>
<li>単体固定ダメージ(遠隔):サジタリウスの弓矢 ← インプ ← B0、B3 ← 〜階</li>
<li>全体ランダムダメージ(遠隔):ガラビ銃 ← 諜報員 ← BC、BE ← 〜階</li>
</ul>
</li>
</ul>
</li>
<li>防具
<ul>
<li>最強1つ手前
<ul>
<li>グランドヘルム ← ドラゴンゴースト ← C0、C3 ← 〜階</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>74階 B8〜BC
75階 BB〜BF
76階 BD〜C1
77階 C0〜C3</p>
<p>79階 C4〜C7</p>
<h2 id="66時間">66〜時間</h2>
<ul>
<li>久しぶり(今日は2022年12月7日)過ぎて状況を覚えてない……</li>
<li>適当に死んだりしたけど、テレポーテーションとメンバー転送を組み合わせると一瞬で全員救出できるから楽になった。</li>
<li>90階を完全踏破。あれこれアビリティポイントが 3じゃなくて5増えるのな。</li>
<li>謎の液体をたくさん入手して、HPと装備ポイントをどんどん上げれば良いっぽい?</li>
<li>98階に足を踏み入れた。これ00階とほとんど同じという構造なのかー。</li>
</ul>
<p>68時間:99階まで?、完全踏87階、最高レベル98</p>
soratokimitonoaidani
pandasのappendができない? もとのDataFrameは変更されないので、返り値を使う
hatenablog://entry/13574176438016503924
2021-09-27T23:39:34+09:00
2022-03-12T11:12:38+09:00 pandasのappendができない? もとのDataFrameは変更されないので、返り値を使う pandasのappend関数を使うときに、たまに間違えて失敗するのでメモ。 pandasでDataFrameにappendするとき、連結後のDataFrameは返り値になっている。もとのDataFrameは変更されない。 以下、詳細。 準備 Python標準のappend pandasのappend おまけ:numpyのappend関数 準備 import pandas as pd import numpy as np pd.options.display.notebook_repr_html …
<p>pandasのappendができない? もとのDataFrameは変更されないので、返り値を使う</p>
<p>pandasのappend関数を使うときに、たまに間違えて失敗するのでメモ。</p>
<p>pandasでDataFrameにappendするとき、連結後のDataFrameは<strong>返り値</strong>になっている。もとのDataFrameは変更されない。</p>
<p>以下、詳細。</p>
<ul class="table-of-contents">
<li><a href="#準備">準備</a></li>
<li><a href="#Python標準のappend">Python標準のappend</a></li>
<li><a href="#pandasのappend">pandasのappend</a></li>
<li><a href="#おまけnumpyのappend関数">おまけ:numpyのappend関数</a></li>
</ul>
<h2 id="準備">準備</h2>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd
<span class="synPreProc">import</span> numpy <span class="synStatement">as</span> np
pd.options.display.notebook_repr_html = <span class="synIdentifier">False</span> <span class="synComment"># jupyter notebook上での出力形式を制御するために書いています。無くても動きます。</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 動作環境の確認</span>
<span class="synIdentifier">print</span>(pd.__version__)
<span class="synIdentifier">print</span>(np.__version__)
<span class="synComment"># --------------------</span>
<span class="synConstant">1.1</span>.<span class="synConstant">2</span>
<span class="synConstant">1.19</span>.<span class="synConstant">1</span>
</pre>
<h2 id="Python標準のappend"><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>標準のappend</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>の普通のリストはappendがインプレースに行われる。</p>
<p>公式ドキュメント:<a href="https://docs.python.org/ja/3/tutorial/datastructures.html">5. データ構造 — Python 3.10.0b2 ドキュメント</a></p>
<pre class="code lang-python" data-lang="python" data-unlink>my_list = [<span class="synConstant">1</span>, <span class="synConstant">3</span>, <span class="synConstant">5</span>]
my_list
<span class="synComment"># --------------------</span>
[<span class="synConstant">1</span>, <span class="synConstant">3</span>, <span class="synConstant">5</span>]
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>my_list.append(<span class="synConstant">7</span>)
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>my_list
<span class="synComment"># --------------------</span>
[<span class="synConstant">1</span>, <span class="synConstant">3</span>, <span class="synConstant">5</span>, <span class="synConstant">7</span>]
</pre>
<p>このとき、append関数の返り値はNoneである。</p>
<pre class="code lang-python" data-lang="python" data-unlink>ret = my_list.append(<span class="synConstant">9</span>)
<span class="synIdentifier">print</span>(ret)
<span class="synComment"># --------------------</span>
<span class="synIdentifier">None</span>
</pre>
<h2 id="pandasのappend">pandasのappend</h2>
<p>pandasではリストはappendがインプレースに行われない。返り値を取ってこなきゃいけない。<br />
<strong>これは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>標準のappendとは違う動きなので、混同しないように注意する必要がある。</strong></p>
<p>公式ドキュメント:<a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.append.html">pandas.DataFrame.append — pandas 1.4.1 documentation</a><br />
仕様はあまりハッキリ書いていないが、
Returns(返り値)が新しいDataFrameであることに注意。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df = pd.DataFrame({<span class="synConstant">'col_A'</span>: [<span class="synConstant">1</span>,<span class="synConstant">2</span>,<span class="synConstant">3</span>], <span class="synConstant">'col_B'</span>: [<span class="synConstant">'p'</span>,<span class="synConstant">'q'</span>,<span class="synConstant">'r'</span>]})
df
<span class="synComment"># --------------------</span>
col_A col_B
<span class="synConstant">0</span> <span class="synConstant">1</span> p
<span class="synConstant">1</span> <span class="synConstant">2</span> q
<span class="synConstant">2</span> <span class="synConstant">3</span> r
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df2 = pd.DataFrame({<span class="synConstant">'col_A'</span>: [<span class="synConstant">100</span>, <span class="synConstant">200</span>], <span class="synConstant">'col_B'</span>: [<span class="synConstant">'x'</span>, <span class="synConstant">'y'</span>]})
df2
<span class="synComment"># --------------------</span>
col_A col_B
<span class="synConstant">0</span> <span class="synConstant">100</span> x
<span class="synConstant">1</span> <span class="synConstant">200</span> y
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 返り値は結合後のDataFrameとなる</span>
df.append(df2)
<span class="synComment"># --------------------</span>
col_A col_B
<span class="synConstant">0</span> <span class="synConstant">1</span> p
<span class="synConstant">1</span> <span class="synConstant">2</span> q
<span class="synConstant">2</span> <span class="synConstant">3</span> r
<span class="synConstant">0</span> <span class="synConstant">100</span> x
<span class="synConstant">1</span> <span class="synConstant">200</span> y
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># もとのDataFrameであるdfは変わっていない</span>
df
<span class="synComment"># --------------------</span>
col_A col_B
<span class="synConstant">0</span> <span class="synConstant">1</span> p
<span class="synConstant">1</span> <span class="synConstant">2</span> q
<span class="synConstant">2</span> <span class="synConstant">3</span> r
</pre>
<p>appendにはinplace引数もない。<br />
ので、dfを新しくしようと思ったら、結果を代入する必要がある。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df = df.append(df2)
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df
<span class="synComment"># --------------------</span>
col_A col_B
<span class="synConstant">0</span> <span class="synConstant">1</span> p
<span class="synConstant">1</span> <span class="synConstant">2</span> q
<span class="synConstant">2</span> <span class="synConstant">3</span> r
<span class="synConstant">0</span> <span class="synConstant">100</span> x
<span class="synConstant">1</span> <span class="synConstant">200</span> y
</pre>
<p>特に、ループの中でうっかり間違えてappendを書くと、ループを抜けても何も追加されていないということが起きる。<br />
(以下の書き方はDataFrameを1行ずつ追加していくものであり、動作が遅くなるのであまり良い方法ではない。説明用の例である)</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># ループの中でappendする例</span>
<span class="synComment"># </span>
df = pd.DataFrame()
<span class="synStatement">for</span> i <span class="synStatement">in</span> <span class="synIdentifier">range</span>(<span class="synConstant">5</span>):
temp = {
<span class="synConstant">'num'</span>: i,
<span class="synConstant">'square'</span>: i**<span class="synConstant">2</span>,
<span class="synConstant">'cubic'</span>: i**<span class="synConstant">3</span>
}
df.append(temp, ignore_index=<span class="synIdentifier">True</span>)
<span class="synComment"># appendの結果を代入していないので、dfはループの中で変わらない</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># dfは空のDataFrameである</span>
df
<span class="synComment"># --------------------</span>
Empty DataFrame
Columns: []
Index: []
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df = pd.DataFrame()
<span class="synStatement">for</span> i <span class="synStatement">in</span> <span class="synIdentifier">range</span>(<span class="synConstant">5</span>):
temp = {
<span class="synConstant">'num'</span>: i,
<span class="synConstant">'square'</span>: i**<span class="synConstant">2</span>,
<span class="synConstant">'cubic'</span>: i**<span class="synConstant">3</span>
}
df = df.append(temp, ignore_index=<span class="synIdentifier">True</span>)
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df
<span class="synComment"># --------------------</span>
cubic num square
<span class="synConstant">0</span> <span class="synConstant">0.0</span> <span class="synConstant">0.0</span> <span class="synConstant">0.0</span>
<span class="synConstant">1</span> <span class="synConstant">1.0</span> <span class="synConstant">1.0</span> <span class="synConstant">1.0</span>
<span class="synConstant">2</span> <span class="synConstant">8.0</span> <span class="synConstant">2.0</span> <span class="synConstant">4.0</span>
<span class="synConstant">3</span> <span class="synConstant">27.0</span> <span class="synConstant">3.0</span> <span class="synConstant">9.0</span>
<span class="synConstant">4</span> <span class="synConstant">64.0</span> <span class="synConstant">4.0</span> <span class="synConstant">16.0</span>
</pre>
<h2 id="おまけnumpyのappend関数">おまけ:numpyのappend関数</h2>
<p>NumPyは公式ドキュメントにこの動作が明示的に説明してあるから良いですね。</p>
<blockquote><p>Note that append does not occur in-place: a new array is allocated and filled.<br />
(拙訳: appendはインプレースではないことに注意してください。新しいNumPy配列が確保されて、そこに値が埋められます。)<br />
<a href="https://numpy.org/doc/stable/reference/generated/numpy.append.html">https://numpy.org/doc/stable/reference/generated/numpy.append.html</a></p></blockquote>
<p>NumPyのappend関数の動きはpandasと同様だ。すなわち、appendの動作はインプレースではなく、追加したあとのNumPy配列を使うには返り値を見る必要がある。</p>
<pre class="code lang-python" data-lang="python" data-unlink>numpy_array = np.array([<span class="synConstant">1</span>, <span class="synConstant">3</span>, <span class="synConstant">5</span>])
numpy_array
<span class="synComment"># --------------------</span>
array([<span class="synConstant">1</span>, <span class="synConstant">3</span>, <span class="synConstant">5</span>])
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 返り値は結合後のNumPy配列となる</span>
other = np.array([<span class="synConstant">2</span>, <span class="synConstant">4</span>])
np.append(numpy_array, other)
<span class="synComment"># --------------------</span>
array([<span class="synConstant">1</span>, <span class="synConstant">3</span>, <span class="synConstant">5</span>, <span class="synConstant">2</span>, <span class="synConstant">4</span>])
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># もとのNumPy配列であるnumpy_arrayは変わっていない</span>
numpy_array
<span class="synComment"># --------------------</span>
array([<span class="synConstant">1</span>, <span class="synConstant">3</span>, <span class="synConstant">5</span>])
</pre>
<p>それでは。</p>
soratokimitonoaidani
4回目の緊急事態宣言と東京都・大阪府の人出の変化を可視化してみた
hatenablog://entry/26006613789371817
2021-07-22T15:17:34+09:00
2021-07-22T15:31:52+09:00 はてなではここ数週間、Knoa氏の匿名ダイアリーによる感染者数予測が耳目を集めている(何だこの矛盾に満ちた表現)。 あんな予測は俺にはできないなと思いつつ、5chのコロナ関連のスレッドをウロウロしていたら、 【公式】モバイル空間統計 | 位置情報などのビッグデータを利用した人口統計情報というデータを見つけたので、ちょっと可視化してみた。予測や分析じゃなくてただの可視化です。 出典は「NTTドコモ モバイル空間統計」である。 東京都 新宿駅 渋谷センター街 東京駅 霞が関 羽田空港 第1ターミナル 大阪府 梅田 感想 データについての注意点 全国主要エリアの15時時点の人口増減率である。(夜間の…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA">はてな</a>ではここ数週間、Knoa氏の匿名ダイアリーによる感染者数予測が耳目を集めている(何だこの矛盾に満ちた表現)。</p>
<p>あんな予測は俺にはできないなと思いつつ、5chのコロナ関連のスレッドをウロウロしていたら、
<a href="https://mobaku.jp/">【公式】モバイル空間統計 | 位置情報などのビッグデータを利用した人口統計情報</a>というデータを見つけたので、ちょっと可視化してみた。予測や分析じゃなくてただの可視化です。<br />
出典は「<a class="keyword" href="http://d.hatena.ne.jp/keyword/NTT%A5%C9%A5%B3%A5%E2">NTTドコモ</a> モバイル空間統計」である。</p>
<ul class="table-of-contents">
<li><a href="#東京都-新宿駅">東京都 新宿駅</a></li>
<li><a href="#渋谷センター街">渋谷センター街</a></li>
<li><a href="#東京駅">東京駅</a></li>
<li><a href="#霞が関">霞が関</a></li>
<li><a href="#羽田空港-第1ターミナル">羽田空港 第1ターミナル</a></li>
<li><a href="#大阪府-梅田">大阪府 梅田</a></li>
<li><a href="#感想">感想</a></li>
</ul>
<p>データについての注意点</p>
<ul>
<li>全国主要エリアの15時時点の人口増減率である。(夜間の人口については何もわからないことに注意)</li>
<li>「緊急事態宣言前」に対する比率である。明確な説明は無いが、おそらく2020/4/7の人口に対する比率だと思われる。(基準はコロナ前ではなく、すでにコロナの影響がある日であることに注意。)</li>
<li>「15時の時点でそのエリアにいた具体的な人数」はグラフになっているのでデータはあるはずだが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>には記載されていない。つらい。</li>
<li>各地点の人口の推移グラフは、サイトトップからたどるのが少し難しいが、<a href="https://mobaku.jp/covid-19/archive/kantokoshinetsu.html">緊急事態宣言前後の人口変動分析</a> などにある。</li>
</ul>
<p>グラフ表示についての注意点</p>
<ul>
<li>横軸に日付、縦軸には2020/4/7 (火曜日)を100としたときの各エリアの人口の値を表示している。
<ul>
<li>エリアの正確な範囲については<a href="https://mobaku.jp/covid-19/archive/kantokoshinetsu.html">緊急事態宣言前後の人口変動分析</a> などを参照</li>
</ul>
</li>
<li>背景の赤色は「緊急事態宣言」の期間、黄色は「蔓延防止等重点措置」の期間を示す。
<ul>
<li>4回目の緊急事態宣言 7/12 〜 8/22 は、とりあえず7月いっぱいを赤色にしている</li>
</ul>
</li>
<li>平日は濃紺(navy)、休日は赤色(red)で表示。</li>
<li>平日と休日の判定は「土曜日もしくは日曜日であるか」のみである。(すなわち、祝日や年末年始は全く考慮していない)</li>
</ul>
<p>取り急ぎでやってみたので上記の通り少し粗がある。本当は感染者数の推移と重ね合わせるのもやりたいんだけど。<br />
<a href="https://mobaku.jp/">【公式】モバイル空間統計 | 位置情報などのビッグデータを利用した人口統計情報</a>は全国のいろいろな箇所の統計を取ってるけど、ここで見るのは基本的に東京都の地点のデータである。最後にちょっとだけ大阪を見てみます。</p>
<h2 id="東京都-新宿駅">東京都 <a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%BD%C9%B1%D8">新宿駅</a></h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20210722/20210722150100.png" alt="f:id:soratokimitonoaidani:20210722150100p:plain" width="1080" height="360" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>グラフ背景に色を付けてみると、東京都に緊急事態が出ている期間って長すぎるだろ! 殆ど出てるだろ! と改めて思ってしまった。
それはさておき、グラフを見ると以下のことが分かる。</p>
<ul>
<li>2回目、3回目の緊急事態宣言の期間中は、平日と休日とも「人口が一度減って、その後増えていく」という傾向を示している。</li>
<li>4回目の緊急事態宣言、7月12日〜で人口は殆ど減少していないように見える。少なくとも2回めや3回目と比べて、減少幅は少ないように見える。</li>
<li>7月17・18日の週末(4回目の緊急事態宣言が出てから最初の週末)は、6月の緊急事態宣言時と比べて人口が多い。</li>
</ul>
<h2 id="渋谷センター街"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%C2%C3%AB%A5%BB%A5%F3%A5%BF%A1%BC%B3%B9">渋谷センター街</a></h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20210722/20210722150121.png" alt="f:id:soratokimitonoaidani:20210722150121p:plain" width="1080" height="360" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<ul>
<li>2回目、3回目の緊急事態宣言の期間中は、平日と休日とも「一度減って、その後増えていく」という傾向を示している。</li>
<li>4月1日前後を極大値として、4月に入ると急激に人出が減少する。何でだろう? 感染者が増えたことで外出を控えたか、単に春休みが終わったか、あたりだろうか。</li>
<li>4回目の緊急事態宣言、7月12日〜で人口は殆ど減少していないように見える。少なくとも2回めや3回目と比べて、減少幅は少ないように見える。</li>
<li>7月17・18日の週末(4回目の緊急事態宣言が出てから最初の週末)は、6月の緊急事態宣言時と比べて人口が多い。</li>
</ul>
<h2 id="東京駅">東京駅</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20210722/20210722150137.png" alt="f:id:soratokimitonoaidani:20210722150137p:plain" width="1080" height="360" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>平日に多いパターンも見たほうが良いかと思い、東京駅を見てみた。<br />
平日の中で一日だけ数値が減少しているのは祝日ですね……(例えば2月11日の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B7%FA%B9%F1%B5%AD%C7%B0%A4%CE%C6%FC">建国記念の日</a>、2月23日の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%B7%B9%C4%C3%C2%C0%B8%C6%FC">天皇誕生日</a>)可能なら本当は色を変えたほうが良いと思う。</p>
<p>新宿や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%C2%C3%AB%A5%BB%A5%F3%A5%BF%A1%BC%B3%B9">渋谷センター街</a>と同様の傾向ですね。</p>
<ul>
<li>2回目、3回目の緊急事態宣言の期間中は、平日と休日とも「人口が一度減って、その後増えていく」という傾向を示している。</li>
<li>4回目の緊急事態宣言、7月12日〜で人口は殆ど減少していないように見える。少なくとも2回めや3回目と比べて、減少幅は少ないように見える。</li>
<li>7月17・18日の週末(4回目の緊急事態宣言が出てから最初の週末)は、6月の緊急事態宣言時と比べて人口が多い。</li>
</ul>
<h2 id="霞が関"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%E2%A4%AC%B4%D8">霞が関</a></h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20210722/20210722150149.png" alt="f:id:soratokimitonoaidani:20210722150149p:plain" width="1080" height="360" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>東京駅とそれほど傾向は変わらない。ので箇条書きは省略。<br />
5月19日(灰色縦線で示したところ)だけが前後の平日よりも顕著に低い。<br />
「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%E2%A4%AC%B4%D8">霞が関</a>の各省庁でテレワークの実体を調査した5月19日だけ、人流がガクンと減り、翌日はまた増えている」という事実が確認できる。下記の記事を参照。</p>
<p><a href="https://mainichi.jp/articles/20210603/k00/00m/010/254000c">霞が関、テレワーク調査日だけ人出減 事前通知「明日だけは」 | 毎日新聞</a></p>
<h2 id="羽田空港-第1ターミナル"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%A9%C5%C4%B6%F5%B9%C1">羽田空港</a> 第1ターミナル</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20210722/20210722150201.png" alt="f:id:soratokimitonoaidani:20210722150201p:plain" width="1080" height="360" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<ul>
<li>2回目の緊急事態宣言の期間中は、はじめに減少していって2月前半が極小値になっている。
<ul>
<li>他の地点と比べて極小値の時期が遅いのは、飛行機に乗るのはチケットを取ってから乗るまでにタイムラグがあるから、そのせい?</li>
</ul>
</li>
<li>3回目の緊急事態宣言の期間中は、5月の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B4%A1%BC%A5%EB%A5%C7%A5%F3%A5%A6%A5%A3%A1%BC%A5%AF">ゴールデンウィーク</a>が終わったあたりが極小値になっている。</li>
<li>ここで一番注目したいのは、2021年7月21日が今年の(ほぼ)最大値になっていることである。
<ul>
<li>7月22日〜25日の4連休の前に休みを取って、空港を利用した ≒ 旅行に出かけた人が一定数いる? 東京から他の地方なのか、他の地方から東京なのかは不明だが、東京以外の感染拡大がこの後発生してもおかしくないと思う。</li>
</ul>
</li>
</ul>
<h2 id="大阪府-梅田"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C2%E7%BA%E5%C9%DC">大阪府</a> 梅田</h2>
<p>最後に大阪を1枚だけ。東京都とはかなり様子が異なる。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20210722/20210722150219.png" alt="f:id:soratokimitonoaidani:20210722150219p:plain" width="1080" height="360" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<ul>
<li>6月<a class="keyword" href="http://d.hatena.ne.jp/keyword/20%C6%FC">20日</a>の前後で全く人口の様子が違う。
<ul>
<li>6月<a class="keyword" href="http://d.hatena.ne.jp/keyword/20%C6%FC">20日</a>の前 は、平日 > 土日</li>
<li>6月<a class="keyword" href="http://d.hatena.ne.jp/keyword/20%C6%FC">20日</a>の後 は、平日 < 土日</li>
</ul>
</li>
<li>大阪は「3回目の緊急事態宣言が出ている間は、土日に自粛して外出を控えた」と推察される。</li>
<li>そして「3回目の緊急事態宣言が解除された6月<a class="keyword" href="http://d.hatena.ne.jp/keyword/20%C6%FC">20日</a>以降、一気に土日に外出するようになった」と推察される。
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C2%E7%BA%E5%C9%DC">大阪府</a>では7月11日頃から感染者数が急激に上昇している。</li>
</ul>
</li>
<li>東京ではこのような「緊急事態宣言の期間中は低いまま、緊急事態宣言の終了を境に一気に人口が増える」という例は見つからず、大阪に特徴的である(<a href="https://mobaku.jp/covid-19/archive/kansai.html#area_4">大阪府の難波の人口</a>も、かなり近い傾向を示している)。</li>
<li>なお、6月に入ってから平日の人口が急に上がるのは、平日の商業施設などの休業要請を6月1日から解除したからだと思われる。下記参照。</li>
</ul>
<blockquote><p>一方、現在、百貨店などの大規模施設に出している休業要請は、土日に限っての要請に切り替え、平日については、夜8時までの時短要請を行います。
<a href="https://www3.nhk.or.jp/news/special/coronavirus/emergency_third/kansai.html#mokuji0">https://www3.nhk.or.jp/news/special/coronavirus/emergency_third/kansai.html#mokuji0</a></p></blockquote>
<h2 id="感想">感想</h2>
<p>考察というほどちゃんとした話ではないので、「感想」ってセクション名にしておきますが。
少なくとも、「緊急事態宣言が出たので外出を控えます」とか「感染者が増えて危ないので外出を控えます」といった行動の変化は、東京都ではほとんど発生していないと考えられる。
(自粛している人は、緊急事態宣言や感染者の数によらず前から自粛している)</p>
<p>一方で、<a href="https://anond.hatelabo.jp/20210621175921">東京の感染者数を5週間ぶん予測した (6月21日版)</a> で参考として示されている<a href="https://www.igakuken.or.jp/r-info/monitoring.html">都内主要繁華街における滞留人口モニタリング(7月18日までのデータ) | 公益財団法人 東京都医学総合研究所</a>を見ると、
東京の繁華街の人口は7月12日の緊急事態宣言以降、明らかな減少傾向にあるように見える。(時間帯別主要繁華街滞留人口の日別推移 というグラフを参照)<br />
特に、上記グラフの基準時刻である15時を含む、昼間でも減少している。 <br />
東京都モニタリング会議でも<a href="https://www.igakuken.or.jp/r-info/monitoring.html">都内主要繁華街における滞留人口モニタリング(7月18日までのデータ) | 公益財団法人 東京都医学総合研究所</a>の分析をもとに「宣言発令後の直近1週間で、レジャー目的の繁華街滞留人口は 減少」と結論づけている。(<a href="https://www.bousai.metro.tokyo.lg.jp/taisaku/saigai/1013388/1014313.html">(第55回)東京都新型コロナウイルス感染症モニタリング会議資料(令和3年7月21日)|東京都防災ホームページ</a>)<br />
上で見てきた傾向と違うのは何故だろうか。<br />
「人口のカウントの仕方の違い」か「エリアの違い」のいずれかだと思うが、よく分からない。</p>
<p>もし追実験したいという奇特な方がいましたら、適当に書いたnotebookを以下に置いてあります。参考にしてください。 <br />
<a href="https://github.com/Linus-MK/fragments_for_blog/blob/master/city_population/mobile_space_stat.ipynb">fragments_for_blog/mobile_space_stat.ipynb at master · Linus-MK/fragments_for_blog · GitHub</a></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a>に関する記事だと、昔こんな記事も書きました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2Fcovid-19_stage" title="新型コロナウイルスの「ステージ」とは何か? 分かりにくかったので調べてまとめた - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/covid-19_stage">linus-mk.hatenablog.com</a></cite></p>
<p>それでは。</p>
soratokimitonoaidani
[pandas/matplotlib]時系列データをプロットするときはデータ型に注意
hatenablog://entry/26006613788006871
2021-07-18T12:43:44+09:00
2021-07-18T12:44:58+09:00 [pandas/matplotlib] 時系列データをプロットするときはデータ型に注意 pandasで時系列データを作って、matplotlibでプロットするときにエラーが出たけど、調べてみたらデータ型(dtype)を間違えていたせいだった。 時系列データのデータ型には気をつけましょう。 という話のメモ。 準備 失敗例 axvspanを実行するとエラーになった 結果には2つの問題点がある。原因は共通で、データ型が不適切だった。 対処法:日付を扱うためのデータ型に変換する 時系列データをのグラフで、axvspan、axvlineを使う 準備 import datetime import pand…
<p>[pandas/matplotlib] 時系列データをプロットするときはデータ型に注意</p>
<p>pandasで時系列データを作って、matplotlibでプロットするときにエラーが出たけど、調べてみたらデータ型(dtype)を間違えていたせいだった。<br />
時系列データのデータ型には気をつけましょう。<br />
という話のメモ。</p>
<ul class="table-of-contents">
<li><a href="#準備">準備</a></li>
<li><a href="#失敗例-axvspanを実行するとエラーになった">失敗例 axvspanを実行するとエラーになった</a></li>
<li><a href="#結果には2つの問題点がある原因は共通でデータ型が不適切だった">結果には2つの問題点がある。原因は共通で、データ型が不適切だった。</a></li>
<li><a href="#対処法日付を扱うためのデータ型に変換する">対処法:日付を扱うためのデータ型に変換する</a></li>
<li><a href="#時系列データをのグラフでaxvspanaxvlineを使う">時系列データをのグラフで、axvspan、axvlineを使う</a></li>
</ul>
<h2 id="準備">準備</h2>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> datetime
<span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd
<span class="synPreProc">import</span> matplotlib.pyplot <span class="synStatement">as</span> plt
pd.options.display.notebook_repr_html = <span class="synIdentifier">False</span> <span class="synComment"># jupyter notebook上での出力形式を制御するために書いています。無くても動きます。</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 動作環境の確認</span>
<span class="synIdentifier">print</span>(pd.__version__)
<span class="synPreProc">import</span> matplotlib
<span class="synIdentifier">print</span>(matplotlib.__version__)
<span class="synComment"># --------------------</span>
<span class="synConstant">1.1</span>.<span class="synConstant">2</span>
<span class="synConstant">3.3</span>.<span class="synConstant">1</span>
</pre>
<h2 id="失敗例-axvspanを実行するとエラーになった">失敗例 axvspanを実行するとエラーになった</h2>
<p>まず適当な時系列データを作ります。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 2021年の祝日を適当に抜き出して並べただけで、データに意味はありません</span>
date_str_list = [<span class="synConstant">'2021-01-11'</span>, <span class="synConstant">'2021-02-11'</span>, <span class="synConstant">'2021-03-20'</span>, <span class="synConstant">'2021-04-29'</span>, <span class="synConstant">'2021-05-05'</span>]
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>val_list = [<span class="synConstant">10</span>, <span class="synConstant">30</span>, <span class="synConstant">20</span>, <span class="synConstant">50</span>, <span class="synConstant">40</span>]
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_date_str = pd.DataFrame({
<span class="synConstant">'date'</span> : date_str_list,
<span class="synConstant">'val'</span> : val_list
})
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_date_str
<span class="synComment"># --------------------</span>
date val
<span class="synConstant">0</span> <span class="synConstant">2021</span>-<span class="synConstant">01</span>-<span class="synConstant">11</span> <span class="synConstant">10</span>
<span class="synConstant">1</span> <span class="synConstant">2021</span>-<span class="synConstant">02</span>-<span class="synConstant">11</span> <span class="synConstant">30</span>
<span class="synConstant">2</span> <span class="synConstant">2021</span>-<span class="synConstant">03</span>-<span class="synConstant">20</span> <span class="synConstant">20</span>
<span class="synConstant">3</span> <span class="synConstant">2021</span>-<span class="synConstant">04</span>-<span class="synConstant">29</span> <span class="synConstant">50</span>
<span class="synConstant">4</span> <span class="synConstant">2021</span>-<span class="synConstant">05</span>-<span class="synConstant">05</span> <span class="synConstant">40</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_date_str.dtypes
<span class="synComment"># --------------------</span>
date <span class="synIdentifier">object</span>
val int64
dtype: <span class="synIdentifier">object</span>
</pre>
<p>さて、matplotlibを使ってこのデータをグラフにする。
そして、axvspan関数を使って、一部の背景に色を付ける……と、何やらエラーが出てきた。<br />
axvspan関数は横軸の範囲を指定して(今回の例では、3月1日〜4月1日)、その範囲に色を付けるmatplotlibの関数である。
下記のページを参考にした。<br />
<a href="https://bunsekikobako.com/axvspan-and-axhspan/">matplotlibで一定区間に背景色をつける方法 – 分析小箱</a></p>
<pre class="code lang-python" data-lang="python" data-unlink>fig, ax = plt.subplots(figsize=(<span class="synConstant">12</span>,<span class="synConstant">4</span>))
ax.plot(df_date_str[<span class="synConstant">'date'</span>], df_date_str[<span class="synConstant">'val'</span>])
<span class="synComment"># 参考:https://bunsekikobako.com/axvspan-and-axhspan/</span>
start_datetime = datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">3</span>,<span class="synConstant">1</span>)
end_datetime = datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">4</span>,<span class="synConstant">1</span>)
ax.axvspan(start_datetime, end_datetime, color=<span class="synConstant">"gray"</span>, alpha=<span class="synConstant">0.3</span>)
<span class="synComment"># --------------------</span>
---------------------------------------------------------------------------
<span class="synType">TypeError</span> Traceback (most recent call last)
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/matplotlib/axis.py <span class="synStatement">in</span> convert_units(self, x)
<span class="synConstant">1519</span> <span class="synStatement">try</span>:
-> <span class="synConstant">1520</span> ret = self.converter.convert(x, self.units, self)
<span class="synConstant">1521</span> <span class="synStatement">except</span> <span class="synType">Exception</span> <span class="synStatement">as</span> e:
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/matplotlib/category.py <span class="synStatement">in</span> convert(value, unit, axis)
<span class="synConstant">60</span> <span class="synComment"># force an update so it also does type checking</span>
---> <span class="synConstant">61</span> unit.update(values)
<span class="synConstant">62</span> <span class="synStatement">return</span> np.vectorize(unit._mapping.__getitem__, otypes=[<span class="synIdentifier">float</span>])(values)
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/matplotlib/category.py <span class="synStatement">in</span> update(self, data)
<span class="synConstant">210</span> <span class="synComment"># OrderedDict just iterates over unique values in data.</span>
--> <span class="synConstant">211</span> cbook._check_isinstance((<span class="synIdentifier">str</span>, <span class="synIdentifier">bytes</span>), value=val)
<span class="synConstant">212</span> <span class="synStatement">if</span> convertible:
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/matplotlib/cbook/__init__.py <span class="synStatement">in</span> _check_isinstance(_types, **kwargs)
<span class="synConstant">2234</span> <span class="synStatement">if</span> <span class="synStatement">not</span> <span class="synIdentifier">isinstance</span>(v, types):
-> <span class="synConstant">2235</span> <span class="synStatement">raise</span> <span class="synType">TypeError</span>(
<span class="synConstant">2236</span> <span class="synConstant">"{!r} must be an instance of {}, not a {}"</span>.format(
<span class="synType">TypeError</span>: <span class="synConstant">'value'</span> must be an instance of <span class="synIdentifier">str</span> <span class="synStatement">or</span> <span class="synIdentifier">bytes</span>, <span class="synStatement">not</span> a datetime.datetime
The above exception was the direct cause of the following exception:
ConversionError Traceback (most recent call last)
<ipython-<span class="synIdentifier">input</span>-<span class="synConstant">8</span>-40d5c36b235b> <span class="synStatement">in</span> <module>
<span class="synConstant">7</span> end_datetime = datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">4</span>,<span class="synConstant">1</span>)
<span class="synConstant">8</span>
----> <span class="synConstant">9</span> ax.axvspan(start_datetime, end_datetime, color=<span class="synConstant">"gray"</span>, alpha=<span class="synConstant">0.3</span>)
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/matplotlib/axes/_axes.py <span class="synStatement">in</span> axvspan(self, xmin, xmax, ymin, ymax, **kwargs)
<span class="synConstant">1105</span>
<span class="synConstant">1106</span> <span class="synComment"># first we need to strip away the units</span>
-> <span class="synConstant">1107</span> xmin, xmax = self.convert_xunits([xmin, xmax])
<span class="synConstant">1108</span> ymin, ymax = self.convert_yunits([ymin, ymax])
<span class="synConstant">1109</span>
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/matplotlib/artist.py <span class="synStatement">in</span> convert_xunits(self, x)
<span class="synConstant">173</span> <span class="synStatement">if</span> ax <span class="synStatement">is</span> <span class="synIdentifier">None</span> <span class="synStatement">or</span> ax.xaxis <span class="synStatement">is</span> <span class="synIdentifier">None</span>:
<span class="synConstant">174</span> <span class="synStatement">return</span> x
--> <span class="synConstant">175</span> <span class="synStatement">return</span> ax.xaxis.convert_units(x)
<span class="synConstant">176</span>
<span class="synConstant">177</span> <span class="synStatement">def</span> <span class="synIdentifier">convert_yunits</span>(self, y):
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/matplotlib/axis.py <span class="synStatement">in</span> convert_units(self, x)
<span class="synConstant">1520</span> ret = self.converter.convert(x, self.units, self)
<span class="synConstant">1521</span> <span class="synStatement">except</span> <span class="synType">Exception</span> <span class="synStatement">as</span> e:
-> <span class="synConstant">1522</span> <span class="synStatement">raise</span> munits.ConversionError(<span class="synConstant">'Failed to convert value(s) to axis '</span>
<span class="synConstant">1523</span> f<span class="synConstant">'units: {x!r}'</span>) <span class="synPreProc">from</span> e
<span class="synConstant">1524</span> <span class="synStatement">return</span> ret
ConversionError: Failed to convert value(s) to axis units: [datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">3</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>), datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">4</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>)]
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20210718/20210718124022.png" alt="f:id:soratokimitonoaidani:20210718124022p:plain" width="703" height="248" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h2 id="結果には2つの問題点がある原因は共通でデータ型が不適切だった">結果には2つの問題点がある。原因は共通で、データ型が不適切だった。</h2>
<p>結果の問題点は2つある。</p>
<ul>
<li>グラフの横軸が等間隔になっている(日付の間隔が違うことが考慮されていない)</li>
<li>axvspanのところでエラーが出た</li>
</ul>
<p>この2つの原因は共通である。データを作るときのデータ型(dtype)がおかしかったのだ。</p>
<p>上で<code>df_date_str.dtypes</code>を実行すると、date型はobjectと書いてある。
これは(やや乱暴にいえば)文字列を入れるための型である。したがって、<strong>pandasやmatplotlibはdate列を日付(時刻)とは解釈せず、文字列として扱っている</strong>。<br />
'2021-01-11'というただの文字で、'AAA', 'BBB' みたいな文字列と全く同じと考えれば良い。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">type</span>(df_date_str.loc[<span class="synConstant">0</span>, <span class="synConstant">'date'</span>])
<span class="synComment"># --------------------</span>
<span class="synIdentifier">str</span>
</pre>
<p>これによって、2つの問題点はいずれも説明がつく。</p>
<ul>
<li><p>グラフの横軸が等間隔になっている(日付の間隔が違うことが考慮されていない)<br />
→ただの文字列として扱っているので、matplotlibは「それぞれの日付の間隔が違う」ことを理解できない。したがって等間隔でグラフを書く。<br />
→今回は元のデータが等間隔でないから気づいたが、元のデータが等間隔(毎日、毎週、毎月……)だと一見して気づかない。</p></li>
<li><p>axvspanのところでエラーが出た<br />
→ただの文字列として扱っているので、matplotlibは「2021年3月1日がグラフ中のどこか?」を理解できない。したがってエラーを出す。</p></li>
</ul>
<h2 id="対処法日付を扱うためのデータ型に変換する">対処法:日付を扱うためのデータ型に変換する</h2>
<p>原因は分かったので、対処法について述べる。<br />
日付を文字列ではなく日付として扱うようにデータを作る必要がある。そのために、datetimeモジュールを使う。</p>
<pre class="code lang-python" data-lang="python" data-unlink>datetime_list = [
datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">1</span>, <span class="synConstant">11</span>),
datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">2</span>, <span class="synConstant">11</span>),
datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">3</span>, <span class="synConstant">20</span>),
datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">4</span>, <span class="synConstant">29</span>),
datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">5</span>, <span class="synConstant">5</span>),
]
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime = pd.DataFrame({
<span class="synConstant">'date'</span> : datetime_list,
<span class="synConstant">'val'</span> : val_list
})
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime
<span class="synComment"># --------------------</span>
date val
<span class="synConstant">0</span> <span class="synConstant">2021</span>-<span class="synConstant">01</span>-<span class="synConstant">11</span> <span class="synConstant">10</span>
<span class="synConstant">1</span> <span class="synConstant">2021</span>-<span class="synConstant">02</span>-<span class="synConstant">11</span> <span class="synConstant">30</span>
<span class="synConstant">2</span> <span class="synConstant">2021</span>-<span class="synConstant">03</span>-<span class="synConstant">20</span> <span class="synConstant">20</span>
<span class="synConstant">3</span> <span class="synConstant">2021</span>-<span class="synConstant">04</span>-<span class="synConstant">29</span> <span class="synConstant">50</span>
<span class="synConstant">4</span> <span class="synConstant">2021</span>-<span class="synConstant">05</span>-<span class="synConstant">05</span> <span class="synConstant">40</span>
</pre>
<p>普通にdataframeを表示しただけでは、「文字列の2021-01-11」と「日付の2021-01-11」は見分けがつかない。<br />
データ型dtypeを確認するのが重要である。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime.dtypes
<span class="synComment"># --------------------</span>
date datetime64[ns]
val int64
dtype: <span class="synIdentifier">object</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">type</span>(df_datetime.loc[<span class="synConstant">0</span>, <span class="synConstant">'date'</span>])
<span class="synComment"># --------------------</span>
pandas._libs.tslibs.timestamps.Timestamp
</pre>
<p>date列が<code>datetime64[ns]</code>となっている。<br />
これは日付や時刻を扱うためのデータ型(dtype)である。</p>
<p>また、最初のDataFrame(<code>df_date_str</code>)から正しいデータを作り直す場合には、文字列のカラムをto_datetimeで日付型に変換する。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime2 = df_date_str.copy()
df_datetime2[<span class="synConstant">'date'</span>] = pd.to_datetime(df_datetime2[<span class="synConstant">'date'</span>])
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime2.dtypes
<span class="synComment"># --------------------</span>
date datetime64[ns]
val int64
dtype: <span class="synIdentifier">object</span>
</pre>
<p><code>df_datetime</code>と<code>df_datetime2</code>は同じデータである。そして<code>df_datetime</code>と<code>df_date_str</code>はデータ型が違うので、見た目は一緒でも違うデータである。
df.equals を使ってDataFrameが同一のものか確認しよう。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime.equals(df_datetime2)
<span class="synComment"># --------------------</span>
<span class="synIdentifier">True</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_datetime.equals(df_date_str)
<span class="synComment"># --------------------</span>
<span class="synIdentifier">False</span>
</pre>
<h1 id="時系列データをのグラフでaxvspanaxvlineを使う">時系列データをのグラフで、axvspan、axvlineを使う</h1>
<p>これで正しいグラフを描ける。</p>
<ul>
<li>グラフの横軸が、日付の間隔を考慮したものになる</li>
<li>axvspanが正しく実行できる(ついでにaxvline関数も入れておいた。こちらは縦線を描く関数。)</li>
</ul>
<p>下記のページを参考にした(再掲)。<br />
<a href="https://bunsekikobako.com/axvspan-and-axhspan/">matplotlibで一定区間に背景色をつける方法 – 分析小箱</a></p>
<pre class="code lang-python" data-lang="python" data-unlink>fig, ax = plt.subplots(figsize=(<span class="synConstant">12</span>,<span class="synConstant">4</span>))
ax.plot(df_datetime[<span class="synConstant">'date'</span>], df_datetime[<span class="synConstant">'val'</span>]) <span class="synComment">#★</span>
<span class="synComment"># 横軸の範囲を指定して、一定区間に背景色をつける</span>
start_datetime = datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">3</span>,<span class="synConstant">1</span>)
end_datetime = datetime.datetime(<span class="synConstant">2021</span>, <span class="synConstant">4</span>,<span class="synConstant">1</span>)
ax.axvspan(start_datetime, end_datetime, color=<span class="synConstant">"gray"</span>, alpha=<span class="synConstant">0.3</span>)
<span class="synComment"># 横軸の位置を指定して、縦線を描く</span>
ax.axvline(datetime.datetime(<span class="synConstant">2021</span>,<span class="synConstant">2</span>,<span class="synConstant">1</span>), color=<span class="synConstant">"red"</span>)
<span class="synComment"># --------------------</span>
<matplotlib.lines.Line2D at <span class="synConstant">0x121f075e0</span>>
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20210718/20210718124026.png" alt="f:id:soratokimitonoaidani:20210718124026p:plain" width="703" height="248" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>pandasやmatplotlibでなんか変だなと思ったら、データ型(dtype)が期待通りになっているかを再確認したほうが良さそうだ。<br />
dtypeについては、以前公式ドキュメントを翻訳したので、そちらも合わせて参照してください。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2F2019%2F11%2F23%2F162709" title="pandasのデータ型、dtypeについて 公式ドキュメントを翻訳した - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/2019/11/23/162709">linus-mk.hatenablog.com</a></cite></p>
<p>それでは。</p>
soratokimitonoaidani
ARC116 D問題 「I Wanna Win The Game」解説
hatenablog://entry/26006613711985556
2021-04-04T00:34:39+09:00
2021-04-04T00:36:08+09:00 AtCoder Regular Contest 116 D問題 「I Wanna Win The Game」解説。 普段は個別問題の解説は書かない。けど、今回は本番中に解けたけど考えすぎてめっちゃ疲れたので、まとめておく。 細かい書き方はやや適当にしています。(個別の問題の解説を見に来る人はそれほど多くないだろうから、きっちり書き上げる重要性は低い) atcoder.jp 各bitの登場回数が分かったら、何通りか分かるか? 合計Mから、各bitへの振り分けを全て考えてみよう 適切な振り分けのための条件 DP なんで解くのに時間がかかったんだろうか しばらくは例1を使って考える。 まず重要なのは…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a> Regular Contest 116 D問題 「I Wanna Win The Game」解説。</p>
<p>普段は個別問題の解説は書かない。けど、今回は本番中に解けたけど考えすぎてめっちゃ疲れたので、まとめておく。<br />
細かい書き方はやや適当にしています。(個別の問題の解説を見に来る人はそれほど多くないだろうから、きっちり書き上げる重要性は低い)</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fatcoder.jp%2Fcontests%2Farc116%2Ftasks%2Farc116_d" title="D - I Wanna Win The Game" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://atcoder.jp/contests/arc116/tasks/arc116_d">atcoder.jp</a></cite></p>
<ul class="table-of-contents">
<li><a href="#各bitの登場回数が分かったら何通りか分かるか">各bitの登場回数が分かったら、何通りか分かるか?</a></li>
<li><a href="#合計Mから各bitへの振り分けを全て考えてみよう">合計Mから、各bitへの振り分けを全て考えてみよう</a></li>
<li><a href="#適切な振り分けのための条件">適切な振り分けのための条件</a></li>
<li><a href="#DP">DP</a></li>
<li><a href="#なんで解くのに時間がかかったんだろうか">なんで解くのに時間がかかったんだろうか</a></li>
</ul>
<p>しばらくは例1を使って考える。</p>
<p>まず重要なのは、bit XORを考える問題は、それぞれのbitを独立に考えれば良い。あるbitの結果は他のbitの結果に全く影響しない。</p>
<p>例1にある</p>
<pre class="code" data-lang="" data-unlink>5 20
---
(1, 2, 3, 7, 7)</pre>
<p>を考えて、それをbitに分解する。bitごとに出現回数を見ると</p>
<ul>
<li>4のbit→2回立っているからbit XOR = 0</li>
<li>2のbit→4回立っているからbit XOR = 0</li>
<li>1のbit→4回立っているからbit XOR = 0</li>
</ul>
<p>となる。合計の20は、<code>4*2 + 2*4 + 1*4 = 20</code>と分解できる。</p>
<h2 id="各bitの登場回数が分かったら何通りか分かるか">各bitの登場回数が分かったら、何通りか分かるか?</h2>
<p>逆に考えると、</p>
<ul>
<li>4のbitが、2回立っている</li>
<li>2のbitが、4回立っている</li>
<li>1のbitが、4回立っている</li>
</ul>
<p>という数列ならば、合計は20であり、そのXORは0なので条件を満たす。</p>
<p>では、このような数列はいくつあるか?</p>
<ul>
<li>4のbitの割り当て方は5C2 = 10通り</li>
<li>2のbitの割り当て方は5C4 = 5通り</li>
<li>1のbitの割り当て方は5C4 = 5通り</li>
</ul>
<p>これをかければよく、<code>10*5*5 = 250通り</code>である。</p>
<h2 id="合計Mから各bitへの振り分けを全て考えてみよう">合計Mから、各bitへの振り分けを全て考えてみよう</h2>
<p>bit XORが0となる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%AC%CD%D7%BD%BD%CA%AC%BE%F2%B7%EF">必要十分条件</a>は、全てのbitに関して登場回数が偶数であることである。
したがって、bit XORが0となるためには、合計Mは偶数でなければならない。したがってMが奇数なら答えは0だ。</p>
<p>いまMを偶数とする。
登場回数は全て偶数なので、2で割ろう。合計もM=20を2で割った10になる。
10を各bitに振り分けるやり方をすべて書き出し、それぞれの場合の数を計算すると、以下の5通りになる。</p>
<pre class="code" data-lang="" data-unlink>10 = 8*0 + 4*2 + 2*1 + 1*0 → 5C0 * 5C4 * 5C2 * 5C0 = 50
10 = 8*0 + 4*2 + 2*0 + 1*2 → 5C0 * 5C4 * 5C0 * 5C4 = 25
10 = 8*0 + 4*1 + 2*2 + 1*2 → 5C0 * 5C2 * 5C4 * 5C2 = 250 (上の例)
10 = 8*1 + 4*0 + 2*1 + 1*0 → 5C2 * 5C0 * 5C2 * 5C0 = 100
10 = 8*1 + 4*0 + 2*0 + 1*2 → 5C2 * 5C0 * 5C0 * 5C4 = 50
↓
合計475</pre>
<h2 id="適切な振り分けのための条件">適切な振り分けのための条件</h2>
<p>上の例では「M/2 = 10 を各bitに振り分けるやり方」を全部考えた。<br />
一般の偶数Mの場合は、どうすれば振り分け方を全部考えられるだろうか?<br />
いっぺんに決めるのは難しそうだ。
上位ビットから決めるか、下位ビットから決めるか。
上位ビットから決めることにしよう。</p>
<p>(N//2 は、N÷2の整数部分を表わす。)<br />
今、振り分けるべき残りの数をrestとし、あるビット(digitと書く)にk個を振り分けたとしよう。(最終的には、N個のうち2k個の数の当該ビットを立てることになる。)</p>
<p>kが適切な値である条件は、以下3つである。</p>
<ul>
<li>0以上 N//2以下である <code>(0 <= k <= N//2)</code></li>
<li>今見ているビットよりも下位の桁に振り分けられる数は高々 <code>(下位ビットの和) * (N//2)</code>である。したがって、振り分けた残りがこれ以下でなければいけない。<code>(rest - digit * k <= (digit-1) * N//2)</code></li>
<li>振り分けた残りが負になってはいけない<code>(rest - digit * k <= (digit-1) * N//2)</code></li>
</ul>
<h2 id="DP">DP</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%B7%B2%BC%A4%EA">天下り</a>的だが、DPを導入する。<br />
(DPに行き着くまでの思考過程は後述する)<br />
M/2を各bitに振り分ける。<br />
DP[bit][rest]を、今からbitの桁に数を振り分けようとしていて、残りの数がrestであるときの、N個の数の決め方、とする。(例えばbitが3だったら2<sup>3</sup> = 8の桁に振り分けようとしている。)</p>
<ul>
<li>初期条件:<code>DP[0][rest] = N C 2*rest</code>
<ul>
<li>最後に1のビットに振り分けるという状態で、残った数がrestである。この場合のN個の数の決め方は <code>N C 2*rest</code> 通りである。</li>
</ul>
</li>
<li>最終的な答え:<code>DP[12][M/2]</code>
<ul>
<li>振り分ける可能性のある最上位桁は、2<sup>12</sup> = 2048である。なぜならM/2は高々2500なので、4096以上のbitに与えたら残りが負になってしまい不適当となるからだ。</li>
</ul>
</li>
<li>漸化式:<code>DP[bit][rest] = SUM(DP[bit-1][rest - (2**bit) * k] * N C 2k)</code> (kの動く範囲は、上記3つの条件を全て満たす範囲)
<ul>
<li>適切なkを選ぶと、それより下位のビットに振り分ける数は<code>rest - (2**bit) * k</code>である。今見ているbitに関しては、N個のうち2k個を選んでビットを立てる。その選び方は<code>N C 2k</code>である。</li>
</ul>
</li>
</ul>
<p>計算量について:<br />
DPテーブルのマス目の個数は12 * M/2 <= 12 * 2500 = 30000<br />
DPテーブルのマス目を1つ計算するための計算量は、正当なkの範囲なので高々 N//2 = 2500<br />
単純にかけると75000000 = 7500万となる。厳しそうだが、kに関する他の条件により実際はこれより少ない。</p>
<h2 id="なんで解くのに時間がかかったんだろうか">なんで解くのに時間がかかったんだろうか</h2>
<p>ここが本来書きたかったパートだわ。<br />
Cが解けたのが40分、Dが解けたのが101分なので、61分もかかっている。これは時間がかかり過ぎたと思う。</p>
<p>コンテスト本番中の思考を再現すると、次のようになる。</p>
<ul>
<li>「M/2 を各bitに振り分けるやり方」を全部列挙して、それぞれについて掛けて最後に足し合わせれば良さそう</li>
<li>上位ビットから順に決めれば良さそう</li>
<li>ということは……現在見ているビットに対して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>関数になる?</li>
<li>しかも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>を全部計算してると同じ状態を何度も計算し直すことになる。そのせいで間に合わない。</li>
<li>メモ化する必要がある。</li>
<li>メモ化<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>? メモ化<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>をちゃんと書くなんてめったに無いぞ? マジで?</li>
<li>あ、メモ化<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>ってことはDPと同等なのか。DPでいいのか?</li>
<li>DPテーブルの定義をこうやると……あ、DPでいけそう。</li>
</ul>
<p>解法の指針がDPだということを確定するまでに時間がかかったんだと思う。</p>
<p>kyopro_friendsさんはメモ化<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>でやってるぽいけど。</p>
<p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A1%BC%A5%D0%A5%EB">サーバル</a>「D問題は、奇数の個数を全探索すると、2進法の1の位は決まって、全体を2で割って小さいサイズの問題にできるよ。メモ化<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>で実装するのが簡単だね」 <a href="https://t.co/bKuZF6Qcim">pic.twitter.com/bKuZF6Qcim</a></p>— <a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>をするフレンズ (@kyopro_friends) <a href="https://twitter.com/kyopro_friends/status/1376178095548297218?ref_src=twsrc%5Etfw">2021年3月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p>
<p>あと、</p>
<ul>
<li>「適切な振り分けのための条件」を考えているときは、上位ビット</li>
<li>しかし、DPテーブルを計算するときは下位ビットから順に計算している</li>
</ul>
<p>というのが腑に落ちない。どこで逆転したんだ?</p>
soratokimitonoaidani
matplotlibが初心者に分かりにくい理由を考える
hatenablog://entry/26006613708988079
2021-03-27T12:49:47+09:00
2021-03-27T13:37:06+09:00 久しぶりにmatplotlibを触ったら、やりたい処理がやりづらい……辛い……と改めて悩んでしまった。 matplotlibが分かりにくくて辛い、という理由を考察する記事である。 matplotlibが初心者にとって分かりにくいのはなぜか? 公式ドキュメント 英語で書かれたPythonブログでこの辺はどう論じられてきたか Practical Business Python: 「Effectively Using Matplotlib」 Real Python 「Python Plotting With Matplotlib (Guide)」 stackoverflow: 「Understand…
<p>久しぶりにmatplotlibを触ったら、やりたい処理がやりづらい……辛い……と改めて悩んでしまった。<br />
matplotlibが分かりにくくて辛い、という理由を考察する記事である。</p>
<ul class="table-of-contents">
<li><a href="#matplotlibが初心者にとって分かりにくいのはなぜか">matplotlibが初心者にとって分かりにくいのはなぜか?</a><ul>
<li><a href="#公式ドキュメント">公式ドキュメント</a></li>
</ul>
</li>
<li><a href="#英語で書かれたPythonブログでこの辺はどう論じられてきたか">英語で書かれたPythonブログでこの辺はどう論じられてきたか</a><ul>
<li><a href="#Practical-Business-Python-Effectively-Using-Matplotlib">Practical Business Python: 「Effectively Using Matplotlib」</a></li>
<li><a href="#Real-Python-Python-Plotting-With-Matplotlib-Guide">Real Python 「Python Plotting With Matplotlib (Guide)」</a></li>
<li><a href="#stackoverflow-Understanding-matplotlib-plt-figure-axarr">stackoverflow: 「Understanding matplotlib: plt, figure, ax(arr)?」</a></li>
</ul>
</li>
</ul>
<h2 id="matplotlibが初心者にとって分かりにくいのはなぜか">matplotlibが初心者にとって分かりにくいのはなぜか?</h2>
<p>データ分析関連でコーディングをしている中で、pandasやnumpyに関しては、自分の知識の範囲を少しずつであっても広げられている実感がある。
例えば、このブログの過去の記事をいくつか見てみると、以下のような点については分かったぞ、と思える。</p>
<ul>
<li><a href="https://linus-mk.hatenablog.com/entry/2019/02/02/200000">pandasのsettingwithcopywarningについては分かったぞ</a></li>
<li><a href="https://linus-mk.hatenablog.com/entry/2019/11/23/162709">pandasのdtypeについては分かったぞ</a></li>
<li><a href="https://linus-mk.hatenablog.com/entry/pnadas_valueerror_len_left_on">pandasでのmergeとjoinの違いについては分かったぞ</a></li>
<li><a href="https://linus-mk.hatenablog.com/entry/numpy_array_ndarray_difference">numpyのndarrayとarrayの違いについては分かったぞ</a></li>
</ul>
<p>このあたりか。やっぱりブログにまとめると知識がしっかり定着するなぁ。<br />
もちろん、pandas/numpyについて全てを知ることは到底無理だ。
しかし、一部については「少なくともこの部分については確固たる知識を習得できた。自分の血肉となった」という自信がある。</p>
<p>でもmatplotlibについては、そうはならない。断片的な知識だけが俺の中にバラバラに存在している。
なぜ知識が断片的になってしまうかというと、</p>
<ul>
<li>2つのインターフェース</li>
<li>ArtistとかFigureとかAxesとかその辺</li>
</ul>
<p>をまず理解しないと、何も始まらないような感覚がある。<br />
土台が固まっていないところの上に何の知識を積んでも、砂上の楼閣になりそうというか。 賽の河原みたいに、知識をいくら積み重ねたところですぐ吹き飛ばされそうというか。<br />
matplotlibだけは、知識の習得の初手が厳しい…… <br />
譬えて言えば、「はい、ここがスタート地点です。先に進むにはまず、この3メートルの壁をよじ登って乗り越えてください。それ以外の方法では次に進めません」みたいな感じ。</p>
<p>そして、たまには「matplotlibの上記の土台を、ちゃんと勉強するか」と一念発起することもある。
3メートルの崖をよじ登って、ArtistとかFigureとかAxesとかその辺を理解しようとするが、それは簡単にいくものではない。と思う。
で、壁からずり落ちてスタート地点から進めない、というのが俺である。</p>
<h3 id="公式ドキュメント">公式ドキュメント</h3>
<p>まずは公式ドキュメントを読め。
誰が書いたのか分からない、Qiitaや個人ブログの断片的な記事を読むよりも、まずは公式ドキュメントを読め。
最も頼りになって信用できる資料は公式ドキュメントに決まってるからな。</p>
<p>……ということはよく言われる。俺もそのとおりだと思う。</p>
<p>上記に関するまとまった意見がないかなと思って「公式ドキュメント」でググったら、「自走<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE%A1%BC">プログラマー</a>」の抜粋版のサイトがあったので載せておきます。<br />
<a href="https://jisou-programmer.beproud.jp/%E5%AE%9F%E8%A3%85%E3%81%AE%E9%80%B2%E3%82%81%E6%96%B9/33-%E5%85%AC%E5%BC%8F%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E3%82%92%E8%AA%AD%E3%82%82%E3%81%86.html">自走プログラマー【抜粋版】 33:公式ドキュメントを読もう</a></p>
<p>しかし、matplotlibは公式ドキュメントすら読む気がしないのは、いったい何故なんだろうか?<br />
自分の行動を振り返ってみると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>本体・pandas・numpy・scikit-learn・seabornは、公式ドキュメントのうち必要なところは読むわ。必要に応じてその都度読んでるわ。<br />
しかしmatplotlib……!<br />
読む……!<br />
読みには行くが分かった気にならない感覚……!<br />
分からない……!<br />
分からないから公式ドキュメントを読みにいかなくなる……!<br />
読みにいかなくなるからますます分からなくなる……!<br />
無限ループ!はまっている、すでに術中……!</p>
<p>なんだか<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%A1%CB%DC%BF%AD%B9%D4">福本伸行</a>っぽくなってしまった。<br />
matplotlibだけは、公式ドキュメントすら読むのを忌避したくなる感覚がある。何故かは分からないけど。「どこに何が書いてあるか」を把握できてないのかな?</p>
<h2 id="英語で書かれたPythonブログでこの辺はどう論じられてきたか">英語で書かれた<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>ブログでこの辺はどう論じられてきたか</h2>
<p>「why matplotlib is hard to understand」とか「matplotlib confusing」とかで検索してみたら、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>関係の英語の技術ブログが見つかった。</p>
<h3 id="Practical-Business-Python-Effectively-Using-Matplotlib">Practical Business <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>: 「Effectively Using Matplotlib」</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>のデータ分析関連ではよく見かける「Practical Business <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>」の記事だ。<br />
<a href="https://pbpython.com/effective-matplotlib.html">https://pbpython.com/effective-matplotlib.html</a></p>
<p>「Why all the negativity towards matplotlib?」の章で、matplotlibが分かりにくい3つの理由が挙げられている。その筆頭が「2つのインターフェース」である。これはもっともだと思う。以下に引用する。</p>
<blockquote><p>First, matplotlib has two interfaces. The first is based on <a class="keyword" href="http://d.hatena.ne.jp/keyword/MATLAB">MATLAB</a> and uses a state-based interface. The second option is an an object-oriented interface. The why’s of this dual approach are outside the scope of this post but <em>knowing</em> that there are two approaches is vitally important when plotting with matplotlib.<br />
The reason two interfaces cause confusion is that in the world of stack overflow and tons of information available via <a class="keyword" href="http://d.hatena.ne.jp/keyword/google">google</a> searches, new users will stumble across multiple solutions to problems that look somewhat similar but are not the same. I can speak from experience. Looking back on some of my old code, I can tell that there is a mishmash of matplotlib code - which is confusing to me (even if I wrote it).</p>
<p>拙訳:
第一に、matplotlibには2つのインターフェースがある。1つ目は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/MATLAB">MATLAB</a>に基づいた、状態ベースのインターフェースである。2つ目は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>のインターフェースである。この2つの方法がある理由についてはこの記事が扱う範囲の外であるが、しかしmatplotlibに2つの方法があると<strong>知っている</strong>ことは、matplotlibを使って図を描く上で極めて重要である。<br />
この2つのインターフェースは混乱の元となる。その理由は、StackOverflowがあってグーグル検索をすれば大量の情報が得られる世界で、初心者がある問題に対して複数の解決法を見つけてしまい、それらがある程度似ているのに同じではないからだ。これは私個人の経験からいってもそうだ。私が昔書いたコードを見返すと、(私自身が書いたのに)自分で読んで分かりにくい、ごちゃ混ぜになったmatplotlibコードが確実にあるのだ。</p></blockquote>
<p>「matplotlibが分かりにくい3つの理由」のうち残りの2つについて。2番目が「デフォルトのスタイルの選択肢の中には、かなり見栄えが悪いものがある(訳注:見た目がきれいでなくて格好悪い、という話)」であった。そして3番めが「図を描くときに、純粋なmatplotlibを使うべきか、pandasやseabornのようなmatplotlibの上層にあるツールを使うべきかに関して分かりにくいこと。」であった。</p>
<p>「分かりにくい理由」を説明した後には具体的なコードを使って書き方の説明をしている。<br />
書き方の説明の部分は、後に改稿してmatplotlibの公式ドキュメントに取り込まれている!<br />
<a href="https://matplotlib.org/stable/tutorials/introductory/lifecycle.html">https://matplotlib.org/stable/tutorials/introductory/lifecycle.html</a></p>
<p>余談であるが、matplotlibに2つの方法がある話は極めて重要である。したがって、matplotlibについてのある程度の量がある記事・本などで、重要な「2つのインターフェース」の話に触れていないものは、matplotlibをロクに分かっていない人が書いたものである可能性が高いと考える。<br />
少なくとも、私が見てきた秀逸な本やネットの記事は、例外なくこの「2つのインターフェース」の話に言及している。</p>
<p>以下の記事も参照。初めて「2つのインターフェース」を俺が知ってビックリしてメモに書いたものだけど。<br />
<a href="https://linus-mk.hatenablog.com/entry/2019/02/10/130640">メモ:Matplotlibのグラフの書き方が2通りある話 - 子供の落書き帳 Renaissance</a></p>
<h3 id="Real-Python-Python-Plotting-With-Matplotlib-Guide">Real <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> Plotting With Matplotlib (Guide)」</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>関係の英語の技術ブログをもう1つ見てみよう。
Real <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> による「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> Plotting With Matplotlib (Guide)」という記事である。<br />
<a href="https://realpython.com/python-matplotlib-guide/">https://realpython.com/python-matplotlib-guide/</a></p>
<p>Why Can Matplotlib Be Confusing?</p>
<blockquote><ol>
<li>The library itself is huge, at something like 70,000 total lines of code.</li>
<li>Matplotlib is home to several different interfaces (ways of constructing a figure) and capable of interacting with a handful of different backends. (Backends deal with the process of how charts are actually rendered, not just structured internally.)</li>
<li>While it is comprehensive, some of matplotlib’s own public documentation is seriously out-of-date. The library is still evolving, and many older examples floating around online may take 70% fewer lines of code in their modern version.</li>
</ol>
<p>拙訳:
1. ライブラリ自体が巨大であり、合計で約70000行もコードがある。
2. matplotlibにはいくつかの異なるインターフェース(図を描く方法)が存在する。少数の異なるバックエンドと相互作用することができる。(バックエンドは内部的な構成だけではなく、どのように図を実際に描画するかという過程も取り扱う。)
3. matplotlibの公式ドキュメントは広範囲にわたるが、その中には非常に古くなったものも存在する(<a href="https://matplotlib.org/3.2.2/users/shell.html">例</a>)。このライブラリは今も進化を続けていて、ネット上に出回っている古い例の中には、新しいバージョンのコードで書き直せば行数が70%少なくなるものもある。</p></blockquote>
<p>matplotlibって実は変化が激しいのか? あんまりそんな印象は無いんだけど。</p>
<h3 id="stackoverflow-Understanding-matplotlib-plt-figure-axarr">stackoverflow: 「Understanding matplotlib: plt, figure, ax(arr)?」</h3>
<p><a href="https://stackoverflow.com/questions/35677767/understanding-matplotlib-plt-figure-axarr">https://stackoverflow.com/questions/35677767/understanding-matplotlib-plt-figure-axarr</a></p>
<p>Understanding matplotlib: plt, figure, ax(arr)?</p>
<blockquote><p>The matplotlib documentation is rather confusing to me. When one searches something really specific, like rescaling a legend, different plot markers and colors and so on the <a class="keyword" href="http://d.hatena.ne.jp/keyword/official">official</a> documentation is really precise but rather general information is not that good in my opinion. Too much different examples, no real explanations of the purposes...looks more or less like a big listing of all possible <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> methods and arguments.</p>
<p>拙訳:matplotlibのドキュメントは、私にとってかなり分かりにくいです。本当に具体的なものを検索するとき、例えば凡例を拡大縮小するとか、プロットのマーカーや色を変えるとかですが、公式ドキュメントは非常に正確です。しかしもっと一般的な情報については私の意見ではそれほど良いものではありません。あまりにも多くの異なる例があって、その目的の説明も無いのです。まるで、全部の<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のメソッドと引数を巨大な一覧表にしたように見えます。</p></blockquote>
<hr />
<p>っていう感じで「やっぱmatplotlibは知識習得しづらいわ」と悩む記事でした。いつかは「matplotlibの根幹をちゃんと理解したわ」っていう記事が書ければ良いんだけど、いつになることやら。</p>
<p>再度書いておくけど、知らなかった人は「matplotlibに2つのインターフェースがある」ことだけは覚えて帰ったほうが良いと思います!</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2F2019%2F02%2F10%2F130640" title="メモ:Matplotlibのグラフの書き方が2通りある話 - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/2019/02/10/130640">linus-mk.hatenablog.com</a></cite></p>
soratokimitonoaidani
クラスタリングの結果を、変数の値に従ってソートする
hatenablog://entry/26006613691479088
2021-02-14T15:09:35+09:00
2021-02-14T17:11:39+09:00 今回の記事の主題は、 クラスタリングの結果(ラベル、番号)を、ある変数の値の順序に従って並び替えるにはどうすればよいか? という話である。 ……しかし、こう書いただけで何のことか分かる人は多分少ないだろう。だから順を追って説明していく。 まずは、今回の問題が起きるクラスタリングの例を作ろう。 クラスタリングの例:2変数・5クラスターのデータをクラスタリングする クラスタリングのラベルを、ある変数の値の順序に従ってソートする方法 クラスタリングの例:2変数・5クラスターのデータをクラスタリングする クラスタリングの対象となるデータの例を適当に作ろう。 scikit-learnのmake_blob…
<p>今回の記事の主題は、<br />
<strong><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>の結果(ラベル、番号)を、ある変数の値の順序に従って並び替えるにはどうすればよいか?</strong><br />
という話である。<br />
……しかし、こう書いただけで何のことか分かる人は多分少ないだろう。だから順を追って説明していく。
まずは、今回の問題が起きる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>の例を作ろう。</p>
<ul class="table-of-contents">
<li><a href="#クラスタリングの例2変数5クラスターのデータをクラスタリングする">クラスタリングの例:2変数・5クラスターのデータをクラスタリングする</a></li>
<li><a href="#クラスタリングのラベルをある変数の値の順序に従ってソートする方法">クラスタリングのラベルを、ある変数の値の順序に従ってソートする方法</a></li>
</ul>
<h2 id="クラスタリングの例2変数5クラスターのデータをクラスタリングする"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>の例:2変数・5<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーのデータを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>する</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>の対象となるデータの例を適当に作ろう。
scikit-learnの<code>make_blob</code>を使って中心を指定し、2変数・5<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーのデータを作成する。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd
<span class="synPreProc">import</span> seaborn <span class="synStatement">as</span> sns
pd.options.display.notebook_repr_html = <span class="synIdentifier">False</span> <span class="synComment"># jupyter notebook上での出力形式を制御するために書いています。無くても動きます。</span>
<span class="synPreProc">import</span> sklearn
<span class="synPreProc">from</span> sklearn.cluster <span class="synPreProc">import</span> KMeans
<span class="synPreProc">from</span> sklearn.datasets <span class="synPreProc">import</span> make_blobs
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 動作環境の確認</span>
<span class="synIdentifier">print</span>(pd.__version__)
<span class="synIdentifier">print</span>(sns.__version__)
<span class="synIdentifier">print</span>(sklearn.__version__)
<span class="synComment"># --------------------</span>
<span class="synConstant">1.1</span>.<span class="synConstant">2</span>
<span class="synConstant">0.11</span>.<span class="synConstant">0</span>
<span class="synConstant">0.24</span>.<span class="synConstant">1</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>sns.set_style(<span class="synConstant">'whitegrid'</span>) <span class="synComment"># seaborn見た目の変更。グラフ内にグリッド線を表示する</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>random_state = <span class="synConstant">123</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 例示用にクラスタリングするデータを作成する</span>
center_coordinates = [[<span class="synConstant">0</span>, <span class="synConstant">0</span>], [<span class="synConstant">1</span>, <span class="synConstant">2</span>], [<span class="synConstant">3</span>, <span class="synConstant">1</span>], [<span class="synConstant">2</span>, <span class="synConstant">3</span>], [<span class="synConstant">4</span>, <span class="synConstant">4</span>]]
n_clusters = <span class="synIdentifier">len</span>(center_coordinates)
X, y = make_blobs(n_samples=<span class="synConstant">30</span>*n_clusters, centers=center_coordinates, n_features=<span class="synConstant">2</span>, cluster_std=<span class="synConstant">0.3</span>, random_state=random_state)
</pre>
<p>データの様子を散布図にしよう。今回はseabornを使う。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df = pd.DataFrame(data=X, columns=[<span class="synConstant">'x1'</span>, <span class="synConstant">'x2'</span>])
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.scatterplot(x=<span class="synConstant">'x1'</span>, y=<span class="synConstant">'x2'</span>, data=df)
ax.set_aspect(<span class="synConstant">'equal'</span>) <span class="synComment"># グラフの縦横比を同じにする 参考:https://xnn.sakura.ne.jp/blog/2019/07/match-the-scatterplot-grid-width-in-matplotlib/</span>
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20210214/20210214150556.png" alt="f:id:soratokimitonoaidani:20210214150556p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>期待通りに5つの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーができていることが見えた。</p>
<p>このデータをk-meansで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>し、結果を出力しよう。
<a href="#f-f4524ff7" name="fn-f4524ff7" title="クラスタリング自体は今回の記事においてそれほど重要ではない。したがって「手法としてk-meansを使う理由」は例を簡潔に説明するために一番シンプルな手法を選んでいるからです。「正解のクラスター数を知っている理由」もクラスタリングを簡単に済ませたいからです。">*1</a></p>
<pre class="code lang-python" data-lang="python" data-unlink>y_pred = KMeans(n_clusters=n_clusters, random_state=random_state).fit_predict(df)
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df[<span class="synConstant">'y_pred'</span>] = y_pred
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df.head()
<span class="synComment"># --------------------</span>
x1 x2 y_pred
<span class="synConstant">0</span> <span class="synConstant">4.190783</span> <span class="synConstant">4.085381</span> <span class="synConstant">0</span>
<span class="synConstant">1</span> <span class="synConstant">1.917537</span> <span class="synConstant">2.575175</span> <span class="synConstant">2</span>
<span class="synConstant">2</span> <span class="synConstant">1.771612</span> <span class="synConstant">3.001094</span> <span class="synConstant">2</span>
<span class="synConstant">3</span> <span class="synConstant">0.992612</span> <span class="synConstant">2.010243</span> <span class="synConstant">1</span>
<span class="synConstant">4</span> <span class="synConstant">1.925955</span> <span class="synConstant">3.020636</span> <span class="synConstant">2</span>
</pre>
<p>ちょっと話が脇道に入るが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>の結果、出力、番号、所属……これをなんと呼ぶか、呼び方に困るんだよね。<a href="https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html">scikit-learn公式のk-meansの説明</a>によると、</p>
<blockquote><p><strong>labels_</strong> ndarray of shape (n_samples,)<br />
Labels of each point</p></blockquote>
<p>と書いてあるので、「<strong><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>の結果、出力、番号</strong>」「<strong>各点がどの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>に分類されたか</strong>」を以降では<strong>ラベル</strong>と呼ぶことにする。</p>
<p>では本題に戻ろう。ラベルによって色を分けて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>の結果を散布図にしよう
<a href="#f-809b0c6f" name="fn-809b0c6f" title="余談:xとyを「機械学習における説明変数がX、目的変数がy」として使っている箇所と、「散布図(scatterplot)を描くときの横軸方向がx、縦軸方向がy」として使っている箇所があるけど、大丈夫だよね?
最初は'cluster_index_pred' という列名にしたけど、scatterplotの凡例が場所を取りすぎて汚くなったのでy_predに変えた。">*2</a>
。</p>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.scatterplot(x=<span class="synConstant">'x1'</span>, y=<span class="synConstant">'x2'</span>, hue=<span class="synConstant">'y_pred'</span>, data=df, palette=<span class="synConstant">'colorblind'</span>)
ax.set_aspect(<span class="synConstant">'equal'</span>)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20210214/20210214150612.png" alt="f:id:soratokimitonoaidani:20210214150612p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>scatterplotで散布図ができた。しかし、この散布図には問題がある。<br />
散布図の上で、ラベル0と1が近い、ラベル3と4が近いというわけではない。
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>のラベルは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>間の近さを考慮して付くわけではないからだ。どういう規則でラベルの番号がついているかは正直謎だが。<br />
(予想:K-meansを使う場合、最初にランダムな点を取るので、それによって最終的な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーの番号が決まるんじゃないか? つまり初期の点の位置を決める乱数次第?)</p>
<p>しかし見づらい場合がある。
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ー番号に規則性が無いので、0番がどこで1番がどこで、と探すのが大変だ。今回は5<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーだからいいけど、もっと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ー数が多い場合は探すのが大変になる。</p>
<h2 id="クラスタリングのラベルをある変数の値の順序に従ってソートする方法"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>のラベルを、ある変数の値の順序に従ってソートする方法</h2>
<p>前提条件を説明するのが遅くなったが、ここまで今回の記事のための問題設定は完了である。</p>
<p><strong><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>のラベルを、ある変数の値の順序に従って並び替えるにはどうすればよいか?</strong></p>
<p>より正確にいうと、今回は、</p>
<ul>
<li>x1の平均が最も小さい<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーがラベル0</li>
<li>x1の平均が2番目に小さい<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーがラベル1</li>
<li>……</li>
</ul>
<p>になるように<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーのラベルを振り直したい、としよう。(他の変数、昇順/降順の場合も同様である)</p>
<p>結論から言うと、このようにすれば良い。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df[<span class="synConstant">'y_pred_sorted'</span>] = df[<span class="synConstant">'y_pred'</span>].replace(
df.groupby(<span class="synConstant">'y_pred'</span>)[<span class="synConstant">'x1'</span>].mean().sort_values().index,
<span class="synIdentifier">range</span>(n_clusters)
)
</pre>
<p>正解を一気に書くと結構長いけど、pandasにある程度慣れていればそこまで難しい話ではない。</p>
<p>ラベルが入った<code>y_pred</code>列の数値を、ある規則によって置換すれば良さそうだ。これにはreplace関数を使えば良い。</p>
<p>置換したい対称は、<code>df['y_pred']</code>の一列だけなので今回はSeriesに対するreplace関数となる。</p>
<p><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.replace.html">https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.replace.html</a></p>
<p>置換の指定方法は色々あって、ドキュメントを見ると細かく書いてある。今回は、list(状のもの)で指定する方法を使う。</p>
<p>「各<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーのx1の平均値はいくつか」は
<code>df.groupby('y_pred')['x1'].mean()</code>
で求まる。<br />
したがって、これをsort_valuesで昇順に並び替え、最後にindexを取れば
「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーのラベルを、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ー内のx1の平均値が小さい順に並び替えたもの」が得られる。</p>
<p>あとは置換後のリストとしてrangeを指定すれば、「置換前のリストと置換後のリスト」が求まる。これをreplaceの引数に入れれば完成である。</p>
<p>最後に、もう一度seabornで散布図を描いてみよう。</p>
<pre class="code lang-python" data-lang="python" data-unlink>ax = sns.scatterplot(x=<span class="synConstant">'x1'</span>, y=<span class="synConstant">'x2'</span>, hue=<span class="synConstant">'y_pred_sorted'</span>, data=df, palette=<span class="synConstant">'colorblind'</span>)
ax.set_aspect(<span class="synConstant">'equal'</span>)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20210214/20210214150632.png" alt="f:id:soratokimitonoaidani:20210214150632p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーが、散布図で左から順に0, 1, 2, ……と並んでいる。
x1の平均値が小さい順に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ー番号を振り直せたことが確認できた。</p>
<div class="footnote">
<p class="footnote"><a href="#fn-f4524ff7" name="f-f4524ff7" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>自体は今回の記事においてそれほど重要ではない。したがって「手法としてk-meansを使う理由」は例を簡潔に説明するために一番シンプルな手法を選んでいるからです。「正解の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ー数を知っている理由」も<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF%A5%EA%A5%F3%A5%B0">クラスタリング</a>を簡単に済ませたいからです。</span></p>
<p class="footnote"><a href="#fn-809b0c6f" name="f-809b0c6f" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">余談:xとyを「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%B3%D8%BD%AC">機械学習</a>における説明変数がX、目的変数がy」として使っている箇所と、「散布図(scatterplot)を描くときの横軸方向がx、縦軸方向がy」として使っている箇所があるけど、大丈夫だよね?<br />
最初は'cluster_index_pred' という列名にしたけど、scatterplotの凡例が場所を取りすぎて汚くなったのでy_predに変えた。</span></p>
</div>
soratokimitonoaidani
新型コロナウイルスの「ステージ」とは何か? 分かりにくかったので調べてまとめた
hatenablog://entry/26006613674060261
2021-01-04T15:24:34+09:00
2021-01-04T15:24:34+09:00 新型コロナウイルスの話で使われている、ステージ3とか4とかいう概念が意味不明すぎる、という話。 私は暇さえあればインターネットばかり見ているような人間だ。私の知る限り、インターネットの世界では、2020年6月に出ていた「東京アラート」については否定的な意見が多かったように思う。「都庁を光らせたいだけだろ」「都民に何をしてほしいのか不明」みたいな意見が見られた。 ただ、この「ステージ」については否定的な意見がそれほど多くない。いや、肯定的な意見も否定的な意見も無い気がするので、誰も注目していないのかもしれない。でもニュースとかだと結構出てくるんだよね。調べてまとめてみたら、意味がよく分からないと…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a>の話で使われている、ステージ3とか4とかいう概念が意味不明すぎる、という話。</p>
<p>私は暇さえあればインターネットばかり見ているような人間だ。私の知る限り、インターネットの世界では、2020年6月に出ていた「東京アラート」については否定的な意見が多かったように思う。「都庁を光らせたいだけだろ」「都民に何をしてほしいのか不明」みたいな意見が見られた。</p>
<p>ただ、この「ステージ」については否定的な意見がそれほど多くない。いや、肯定的な意見も否定的な意見も無い気がするので、誰も注目していないのかもしれない。でもニュースとかだと結構出てくるんだよね。調べてまとめてみたら、意味がよく分からないところが多かった。</p>
<ul class="table-of-contents">
<li><a href="#注意事項免責事項">注意事項、免責事項</a></li>
<li><a href="#ステージという概念はいつ誰が言い出したのか">「ステージ」という概念は、いつ誰が言い出したのか?</a></li>
<li><a href="#どのステージなのかの判断は指標から自動的に決まるのか">どのステージなのかの判断は、指標から自動的に決まるのか?</a></li>
<li><a href="#この県はステージいくつですを誰が決めるのか">「この県はステージいくつです」を誰が決めるのか?</a></li>
<li><a href="#分科会がステージを判断してはダメなの">分科会がステージを判断してはダメなの?</a></li>
<li><a href="#ステージという概念はどの程度活用されているのか">ステージという概念はどの程度活用されているのか?</a></li>
<li><a href="#各都道府県はステージいくつなのか">各都道府県はステージいくつなのか?</a><ul>
<li><a href="#ステージ3">ステージ3</a></li>
<li><a href="#ステージ2">ステージ2</a></li>
</ul>
</li>
<li><a href="#分科会のお願いは一体誰に向けたお願いなのだろうか">分科会の「お願い」は一体誰に向けたお願いなのだろうか?</a></li>
<li><a href="#ここまでの感想">ここまでの感想</a></li>
<li><a href="#参考リンク">参考リンク</a></li>
</ul>
<h2 id="注意事項免責事項">注意事項、免責事項</h2>
<p>私は報道関係者でも医療関係者でも行政関係者でもなく、一介のエンジニアです。</p>
<p>本記事の内容については細心の注意を払っておりますが、コンテンツの内容が正確であるかどうか、最新のものであるかどうか、安全なものであるか等について保証をするものではなく、何らの責任を負うものではありません。また、執筆者は通知することなく本記事に掲載した情報の訂正、修正、追加、中断、削除等をいつでも行うことができるものとします。<br />
また、本記事のご利用により、万一、ご利用者様に何らかの不都合や損害が発生したとしても、執筆者は何らの責任を負うものではありません。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B8%FC%C0%B8%CF%AB%C6%AF%BE%CA">厚生労働省</a>などの資料では「ステージIII」のようにローマ数字を使っていますが、本記事では「ステージ3」などの算用数字表記で統一します。ニュースとかで見るときは、ほぼ全部算用数字だし。</p>
<h2 id="ステージという概念はいつ誰が言い出したのか">「ステージ」という概念は、いつ誰が言い出したのか?</h2>
<p><strong>Q. 「ステージ」という概念は、いつ誰が言い出したのか?</strong><br />
<strong>A. 2020年8月7日、政府の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a>分科会が提唱した。</strong></p>
<p><a href="https://www.cas.go.jp/jp/seisaku/ful/yusikisyakaigi.html">https://www.cas.go.jp/jp/seisaku/ful/yusikisyakaigi.html</a><br />
「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%B6%C0%F7%BE%C9">感染症</a>対策分科会」の「令和2年 8月7日 第5回資料 今後想定される感染状況と対策について」で、このステージという用語が書いてある。ここで「ステージ」という概念が初めて登場したのだと思う。</p>
<blockquote><p>ステージ3<br />
感染者の急増及び医療提供体制における大きな支障の発生を避けるための対応が必要な段階<br />
ステージ2と比べて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーが広範に多発する等、感染者が急増し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%B6%C0%F7%BE%C9">感染症</a>に対する医療提供体制への負荷がさらに高まり、一般医療にも大きな支障が発生することを避けるための対応が必要な状況。</p>
<p>ステージ4<br />
爆発的な感染拡大及び深刻な医療提供体制の機能不全を避けるための対応が必要な段階<br />
病院間<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ー連鎖などの大規模かつ深刻な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ー連鎖が発生し、爆発的な感染拡大により、高齢者や高リスク者が大量に感染し、多くの重症者及び死亡者が発生し始め、公衆衛生体制及び医療提供体制が機能不全に陥いることを避けるための対応が必要な状況。<br />
(今後想定される感染状況と対策について p.3より なおローマ数字は算用数字に直した)</p></blockquote>
<p>7月31日段階で、分科会は「(1)感染ゼロ散発段階(2)感染漸増段階(3)感染急増段階(4)感染爆発段階」という4段階に分けることを提案している(<a href="https://news.yahoo.co.jp/articles/7144a4abf31c94a588b8bc20cabc7e4ec9f1ec74">https://news.yahoo.co.jp/articles/7144a4abf31c94a588b8bc20cabc7e4ec9f1ec74</a>)。具体的な指標と基準値を定めたのが8月7日だな。</p>
<h2 id="どのステージなのかの判断は指標から自動的に決まるのか">どのステージなのかの判断は、指標から自動的に決まるのか?</h2>
<p><strong>Q. どのステージなのかの判断は、指標から自動的に決まるのか?</strong><br />
<strong>A. いいえ。各指標の数値はあくまで「目安」であり、どのステージなのかは総合的に判断する。</strong></p>
<blockquote><p>ただ尾身会長は、こうした数値はあくまで「目安」であり、1つでも数値が基準値を超えたら<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%C5%AA">機械的</a>に次のステージに移行するわけではないと強調。「指標は国、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C3%CF%CA%FD%B8%F8%B6%A6%C3%C4%C2%CE">地方公共団体</a>が総合的に判断するための目安であり、地域の実情に合わせた対策を講じる」必要があると説明した。
<a href="https://news.yahoo.co.jp/articles/6aca60a0f5e781f2a732e86c5173632dbfaa52a7">https://news.yahoo.co.jp/articles/6aca60a0f5e781f2a732e86c5173632dbfaa52a7</a></p></blockquote>
<h2 id="この県はステージいくつですを誰が決めるのか">「この県はステージいくつです」を誰が決めるのか?</h2>
<p><strong>Q. では、「この県はステージいくつです」を決めるのは誰か?</strong><br />
<strong>A. おそらく、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県と国</strong></p>
<p>分科会の「令和2年 8月7日 第5回資料 今後想定される感染状況と対策について」資料より。</p>
<blockquote><p>提案する指標は「あくまで目安」であり、また、一つひとつの指標をもって<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%C5%AA">機械的</a>に判断するのではなく、国や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県はこれらの指標を「総合的に判断」して、感染の状況に応じ積極的かつ機動的に対策を講じていただきたい。<br />
( 今後想定される感染状況と対策について p.4より)<br />
以下の指標は目安であり、また、これらの指標をもって<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%C5%AA">機械的</a>に判断するのではなく、国や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県はこれらの指標を総合的に判断していただきたい。<br />
( 今後想定される感染状況と対策について p.5より)</p></blockquote>
<p>この資料を読むと「国や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県は」と、国と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県を並列に並べて判断主体にしている気がする。</p>
<p>しかし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県知事、と単に書いてある記事もある。うーん、よく分からない。</p>
<blockquote><p>Q:誰がどうステージを決めるの?<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県のステージを判断するのは、各々の知事という立て付けになっています。<br />
<a href="https://news.yahoo.co.jp/articles/6aca60a0f5e781f2a732e86c5173632dbfaa52a7?page=2">https://news.yahoo.co.jp/articles/6aca60a0f5e781f2a732e86c5173632dbfaa52a7?page=2</a></p>
<p>分科会は「指標はあくまで目安」とする。尾身氏は「現場を知っているのは知事さん。知事が主体的にやるべきだ」と判断を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県に委ねた。<br />
<a href="https://www.tokyo-np.co.jp/article/47720">https://www.tokyo-np.co.jp/article/47720</a></p>
<p>これまで、どの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県もステージ2以下とみなされてきた。11月に入って北海道や東京都などでは、分科会が示したステージ3の六つの指標のうち多くで上回るが、判断は知事に委ねられ、分科会のステージに即した対策の議論は進んでいなかった。
<a href="https://www.asahi.com/articles/ASNCN6QCWNCNULBJ01P.html">https://www.asahi.com/articles/ASNCN6QCWNCNULBJ01P.html</a></p></blockquote>
<h2 id="分科会がステージを判断してはダメなの">分科会がステージを判断してはダメなの?</h2>
<p><strong>Q. 分科会がステージという概念を作ったんでしょ? 分科会がステージを判断しちゃダメなの?</strong><br />
<strong>A. 分科会が「個人的な意見」としていくつかの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県を挙げたことはある。しかし、分科会は判断するのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県と国だという姿勢であり、分科会が判断することに対して否定的だ。</strong></p>
<p>各<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県を名指しで挙げたことはある。11月<a class="keyword" href="http://d.hatena.ne.jp/keyword/20%C6%FC">20日</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a>対策分科会の会見だ。分科会が判断するわけではないから、専門家の個人的な意見だけど、という留保がついている。</p>
<blockquote><p>「(中略)現在の感染状況を考えれば、いくつかの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県でステージ3相当と判断せざるを得ない状況に、早晩至る可能性が高いとわれわれは判断している」と述べ、厳しい状況の地域が複数あるとの認識を示した。質疑で具体的な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県名を問われると「専門家としての個人的な意見」と前置きしたうえで「北海道の札幌はステージ3に入っているんじゃないか。東京や大阪などはステージ3に近づきつつある」と言及した。<br />
<a href="https://news.yahoo.co.jp/articles/57194ece0c8ecb6f4b7746d7fac2ded63e1d2513">https://news.yahoo.co.jp/articles/57194ece0c8ecb6f4b7746d7fac2ded63e1d2513</a></p></blockquote>
<p>その後、11月25日の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a>対策分科会の会見でも、同様に留保をつけつつ地域名を挙げている。</p>
<blockquote><p>その地域がどのステージに相当するかを判断するのは「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県が政府と連携してやる」ことで、「判断するのは我々の仕事ではない」と述べた。<br />
しかし、記者からさらに具体的な地域名を求められると「(分科会としての)判断ではない」と断ったうえで、「おそらく札幌は(入る)。それから島しょは別だが、23区も。東京の場合は、以前は一部地域だったけど23区を中心に感染が、ほとんどの地域に拡散している。あとは、これも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%BE%B8%C5%B2%B0%BB%D4">名古屋市</a>もそう(ステージ3相当)じゃないか。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C2%E7%BA%E5%BB%D4">大阪市</a>なんかもそれだとわれわれは考えている」と語り、札幌市、東京23区、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%BE%B8%C5%B2%B0%BB%D4">名古屋市</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C2%E7%BA%E5%BB%D4">大阪市</a>が該当するとの見解を示した。<br />
<a href="https://news.yahoo.co.jp/articles/8f973cdbbf30ff3b5aefedceb8b1cdad781cd9dd">https://news.yahoo.co.jp/articles/8f973cdbbf30ff3b5aefedceb8b1cdad781cd9dd</a></p></blockquote>
<p>ただ、分科会はステージの判断に対して「あくまで参考」という立場を崩していないようだ。<br />
12月11日の会見では、記者が「分科会がステージ判断をした方がよいのでは」と質問したのに対して、分科会の尾身会長が否定している。「ステージを判断するのは、分科会の役割ではないから」という理由のようだ。</p>
<p>(12月11日の会見では、ステージ3を「減少」「高止まり」「拡大継続」という3つの「シナリオ」に分割する話があった。が、この「シナリオ」という話は、ステージ分類に輪をかけてよくわからないので、この記事では大きく扱わない)</p>
<blockquote><p>その地域の感染状況がどのステージに該当するかのステージ判断は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県知事と国が連携して決めることになっている。前述の通り、分科会はステージ3相当の地域ではGo Toトラベルを一時停止することを求めているが、Go Toトラベルからの除外を検討する局面で国と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BC%AB%BC%A3">自治</a>体の間でボールを投げ合うようなケースもあった。<br />
会見では、むしろステージ判断自体を専門家が主導する方が早いのではないかとの質問も出たが、尾身会長は役割分担の明確化を挙げて反論した。<br />
「分科会(の役割)は対策を提案することで、実行するのは我々の仕事ではない。ここが専門家と政府の役割(分担)で、そのことが曖昧になったのが当初の専門家会議」<br />
さらに言葉を強めて続けた。「ステージ3というのは、こういう状況を言うと(分科会は)ここまで示している。普通にやればステージ2なのかステージ3なのか分かるような書き方を(している)。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BC%AB%BC%A3">自治</a>体と国は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県民・国民のために今まで以上の英断を、決断、判断をしてほしい」
<a href="https://news.yahoo.co.jp/articles/f793ea3f22baa81eb02e2f82f11574522a1c2000?page=2">https://news.yahoo.co.jp/articles/f793ea3f22baa81eb02e2f82f11574522a1c2000?page=2</a></p>
<p>分科会のこの日の記者会見では、政府や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県ではなく、分科会がステージ判断をした方がよいのでは、という質問が出たが尾身茂会長は否定した。<br />
今春の「第1波」の際、医学的見地から対策を助言した「専門家会議」は「政府との役割分担が曖昧」と批判を浴び、現在の分科会に衣替えした。政策決定には踏み込まないようにしており、尾身会長は「知事が早く判断していただきたい。早めに手を打ってください」と訴えた。<br />
<a href="https://www.tokyo-np.co.jp/article/73854">https://www.tokyo-np.co.jp/article/73854</a></p></blockquote>
<h2 id="ステージという概念はどの程度活用されているのか">ステージという概念はどの程度活用されているのか?</h2>
<p><strong>Q. このステージという概念はどの程度活用されているのか?</strong></p>
<p><strong>A. <a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県が独自に警戒レベルを作っているところが多く、分科会の定めるステージを活用している<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県はそれほど多くない。</strong> ただ分科会は基本的に「ステージ」を使って話をしていると思う</p>
<p>各<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県が「どのような指標や警戒レベルを使っているか」については日経の記事がよくまとまっていた。<br />
<a href="https://www.nikkei.com/article/DGXZQODG115Z7011122020000000">https://www.nikkei.com/article/DGXZQODG115Z7011122020000000</a></p>
<p>国はこの「ステージ1〜4」、北海道は独自の「ステージ1〜5」、東京は「管理状況と医療提供体制について、それぞれ4段階」などなど。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県によって使うレベルはバラバラなのだ。</p>
<p>ただ、分科会がコメントするときは基本的に「ステージ2」「ステージ3」という概念を使って話をする。例えば、Go To トラベルとの関係だと、「ステージ3」ならGo Toは中止(<a href="https://www.asahi.com/articles/ASND942ZXND9ULBJ006.html">尾身氏「ステージ3地域、GoTo停止を」 衆院厚労委</a> / <a href="https://www.jiji.com/jc/article?k=2020111200527&g=pol">感染急拡大ならGoTo停止も コロナ「大流行に最大警戒」―政府</a>)、「ステージ2」ならばGo Toを再開してもよい(<a href="https://www.jiji.com/jc/article?k=2020121700972&g=pol">ステージ2なら事業再開 GoTo一時停止で―尾身氏</a>)と発言している。</p>
<blockquote><p>政府の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%B6%C0%F7%BE%C9">感染症</a>対策分科会の尾身茂会長は17日の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%B2%B1%A1">参院</a>内閣委員会の閉会中審査で、年末年始に全国で一時停止する国の観光支援事業「Go To トラベル」に関し、東京都や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C2%E7%BA%E5%BB%D4">大阪市</a>の状況が感染の漸増を示す「ステージ2」まで改善すれば、全国で事業を再開しても問題ないとの考えを示した。<br />
<a href="https://www.jiji.com/jc/article?k=2020121700972&g=pol">https://www.jiji.com/jc/article?k=2020121700972&g=pol</a></p></blockquote>
<p>では、それぞれの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県はどこのステージなのか、を知りたくなるだろう。それが次の問題だ。</p>
<h2 id="各都道府県はステージいくつなのか">各<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県はステージいくつなのか?</h2>
<p><strong>Q. 各<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県はステージいくつなのか?</strong><br />
<strong>A. 一覧は無い。</strong></p>
<p>「この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県は現在ステージいくつ」という一覧表はあるかなと探したが、見つからなかった。</p>
<h3 id="ステージ3">ステージ3</h3>
<p>「ステージ3と判断した」という地域は探した限り以下の通りである。(判断した日付の順に
並んでいる)</p>
<ul>
<li>北海道札幌市 ステージ3 2020年11月24日 (<a href="http://www.pref.hokkaido.lg.jp/ss/ssa/koronataisakukaigi.htm">http://www.pref.hokkaido.lg.jp/ss/ssa/koronataisakukaigi.htm</a> →「第27回】 令和2年11月24日(火)開催 資料1 国のステージ3相当の判断について」)</li>
<li>埼玉県 ステージ3 2020年12月28日 (<a href="https://www.tokyo-np.co.jp/article/77173">https://www.tokyo-np.co.jp/article/77173</a>)</li>
<li>神奈川県 ステージ3 2020年12月30日 (<a href="https://www.yomiuri.co.jp/national/20201230-OYT1T50197/">https://www.yomiuri.co.jp/national/20201230-OYT1T50197/</a>)</li>
</ul>
<p>最も感染者数が多い東京はいくつなのか? 「コロナ ステージ 東京」で検索したけど、「東京都はステージいくつです」と判断したという記述は無かった。(尾身会長は東京都をステージ3相当だと述べているけど、それはあくまで参考意見である。)<br />
ところで、2021年1月2日には東京都などが政府に対して緊急事態宣言を発出するよう要請した。ステージ分類の資料では、ステージ4では「緊急事態宣言など、強制性のある対応を検討せざるを得ない(今後想定される感染状況と対策について p.8より)」と書いてある。ということは、東京都はステージ4に入っているか、入りそうになっているか、そのどちらかの状態だろう。しかし東京都自身は、現在に至るまで、ステージ3だとも4だとも明言していない。ここまで考えると、東京はこのステージという概念をほぼ無視している、と考えるのが妥当な気がする。</p>
<p>なお2020年12月9日の時点では、ステージ3に該当すると判断された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県は無いらしいです。</p>
<blockquote><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%C3%C6%A3%BE%A1%BF%AE">加藤勝信</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%B1%CB%BC%C4%B9%B4%B1">官房長官</a>は9日の記者会見で「現時点でステージ3に該当すると判断された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県はないと承知している」と話した。<br />
<a href="https://www.nikkei.com/article/DGXZQOFS098U30Z01C20A2000000">https://www.nikkei.com/article/DGXZQOFS098U30Z01C20A2000000</a></p></blockquote>
<h3 id="ステージ2">ステージ2</h3>
<p>また、ステージ2に該当すると判断した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県は探した限り以下の通りである。</p>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%AD%C5%E7%B8%A9">広島県</a> ステージ1→2 2020年11月30日(<a href="https://www.pref.hiroshima.lg.jp/soshiki/19/covid19-stage.html">https://www.pref.hiroshima.lg.jp/soshiki/19/covid19-stage.html</a>)</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%C5%B2%AC%B8%A9">静岡県</a> ステージ2で据え置き(ステージ2にギリギリでとどまっている状態) (<a href="https://mainichi.jp/articles/20201202/ddl/k22/040/119000c">https://mainichi.jp/articles/20201202/ddl/k22/040/119000c</a>)</li>
</ul>
<p>なお調べている中で興味深い記事があった。神奈川県の状況について記した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%EC%B5%FE%BF%B7%CA%B9">東京新聞</a>の記事だ。記事の日付は2020年12月22日なので、上記の「神奈川県 ステージ3」よりも前だ。「複数の県幹部が「ステージ引き上げに強く反対したのは、政府と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%A3%C9%CD%BB%D4">横浜市</a>だ」と断言した」らしい。<br />
12月14日に、政府はGo To トラベルを全国一斉に一時停止することを決定している。12月14日より前に神奈川県を「ステージ3」に引き上げようとすると、そこだけGo To トラベルを停止する必要があるはずだ。</p>
<blockquote><p>十一月以降、感染状況を表す七指標のほとんどが「ステージ3」(感染急増)に達しても、ステージ引き上げは判断しなかった。(中略)<br />
「強いメッセージを出して感染増を抑える」ことを重視する知事が、最も端的に危機感を伝えられる「ステージ引き上げ」をしないのは、どう考えても異様だった。(中略)<br />
ステージを引き上げなかった事情を問われた知事は「じくじたる思い」「県と国、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%AF%CE%E1">政令</a>市が一枚岩にならないといけない」と話した。思い切った判断ができない背景に、政府や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%AF%CE%E1">政令</a>市の意向があることを強くうかがわせた。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%A3%C9%CD%BB%D4">横浜市</a>は認めていないが、複数の県幹部が「ステージ引き上げに強く反対したのは、政府と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%A3%C9%CD%BB%D4">横浜市</a>だ」と断言した。<br />
<a href="https://www.tokyo-np.co.jp/article/75853">https://www.tokyo-np.co.jp/article/75853</a></p></blockquote>
<h2 id="分科会のお願いは一体誰に向けたお願いなのだろうか">分科会の「お願い」は一体誰に向けたお願いなのだろうか?</h2>
<p>分科会の最新の資料は、「第19回資料 現在直面する3つの課題」という2020年12月23日の資料である。<br />
この中の19〜24ページには「皆さんへのお願い」が書かれている。
その中でp.23を見てみよう。</p>
<blockquote><p>シナリオ3の地域の皆さんへ<br />
(中略)そのため、シナリオ3の地域では、年末年始に向けて、次のことをお願いします。
1. 忘年会・新年会は基本的に見送ってください。
2. 帰省(とりわけ感染地域とそれ以外の地域での往来)も、ご家族と相談の上、控えることや延期・分散も含め慎重に検討してください。<br />
3. イルミネーションについては早めの消灯。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A5%A6%A5%F3%A5%C8%A5%C0%A5%A6%A5%F3%A5%A4%A5%D9%A5%F3%A5%C8">カウントダウンイベント</a>などについてもオンラインを活用した形で開催。いずれにしても混雑する時間は避けることなどをお願いします。</p></blockquote>
<p>ああ、「シナリオ3の地域の皆さん」は忘年会新年会をやるなという要請を分科会もしてたんだ。知らなかったわ。<br />
3はイルミネーションやイベントの主催者に向けたお願いだろう。1、2は一般市民へのお願いだろう。お願いする相手が違うものを一緒くたに載せるのはどうなのかと思うのだけど。それよりも問題なのは、お願いする相手が誰なのか不明だという点である。</p>
<ul>
<li>これは、ステージ3(感染急増)の中のシナリオ3(拡大継続)の地域の住民に対して分科会がお願いした事項である</li>
<li>ステージやシナリオの判断は「国と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県が連携して」やってくれ、と分科会はいう</li>
<li>少なくともこの時点(12/23)でステージ3と宣言したのは北海道札幌市だけ</li>
<li>さらにステージ3の中でどのシナリオだと宣言した地域はない(私の知る限り)</li>
<li>じゃあこれは一体誰に向けたお願いなのだろうか?????</li>
</ul>
<h2 id="ここまでの感想">ここまでの感想</h2>
<p>乱暴にまとめると、下みたいな感じの理解で良いのかな? 分科会と国と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県が全てバラバラに動いているのが分かった。分科会は「ステージ」という概念に立脚して話をしようとしている、しかし「ステージ」は多くの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県が採用していないので、根無し草のような議論になってしまう。話が噛み合ってないというわけだ。</p>
<ul>
<li>分科会「どのステージなのかは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県が国と連携して判断してね」</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県「いや、うちはこの独自基準で運用するんで。国のステージは分かりにくいから、使わなくていいや」</li>
<li>国「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県が何も言ってこないから、ステージ3の地域はありません」</li>
<li>分科会「ステージ3の地域ではGoToは中止すべき」</li>
<li>俺「それはどこだよ」</li>
<li>分科会「いや、ステージ3を判断するのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県と国だけど」</li>
<li>分科会「ステージ3の中のシナリオ3の地域の皆さん!忘年会と新年会はやめてください!」</li>
<li>俺「だからそれはどこだよ」</li>
<li>分科会「いや、ステージとシナリオを判断するのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県と国だけど」</li>
</ul>
<p>結局、「ステージ」がどういうふうに使われているか、を考えると、あれだわ。ニュース番組や情報番組が「各<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県でステージ3と4の指標をこんなに上回っています! 東京も! 大阪も!」って表にまとめている。テレビを見た人が「ふーん、感染が拡大してるね、医療が逼迫してるね」って理解する、そのときだけ使われている気がする。個人的には、<strong>ステージという概念は何かの意思決定の判断根拠にはなってはいない</strong>、という理解である。</p>
<h2 id="参考リンク">参考リンク</h2>
<p>素人がまとめたものよりも、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a>「ステージ」に関するちゃんとした記事を見たいという人は、以下の記事をご覧ください。</p>
<p><a href="https://news.yahoo.co.jp/articles/6aca60a0f5e781f2a732e86c5173632dbfaa52a7">【Q&A】新型コロナ報道で耳にする「ステージ」って何?</a> 2020年10月13日の記事。</p>
<p><a href="https://news.yahoo.co.jp/articles/639fb81498af7e41adf108fbe47e686073bb6737">【Q&A】コロナ分科会が提言。“ステージ3地域”の「3つのシナリオ」とは?</a> 2020年12月12日の記事。分科会が新たに言い出した「シナリオ」の話。</p>
<p><a href="https://www.m3.com/open/iryoIshin/article/851271/">新型コロナ対応の目安、「ステージ」とは</a> 2020年12月7日の記事。リンクで飛ぶと「会員限定です」と書いてあって記事が見られないが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>検索からだと記事内容を閲覧できる。</p>
<p><a href="https://www3.nhk.or.jp/news/special/coronavirus/committee/detail/detail_23.html">政府の新型コロナ分科会 新型コロナ 各地で異なる“ステージ”分け</a> 2020年11月17日の記事。</p>
<p><a href="https://hazard.yahoo.co.jp/article/20200813">新型コロナ 感染状況のステージと6指標</a> 毎週金曜日に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B8%FC%C0%B8%CF%AB%C6%AF%BE%CA">厚生労働省</a>が「各<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%D4%C6%BB">都道</a>府県の指標の値」をまとめている。それを見やすくしたのがこのYahoo内の表である。ステージ3や4の指標を超えた地域には色を付けている。</p>
soratokimitonoaidani
AtCoder青になりました
hatenablog://entry/26006613666200341
2020-12-17T01:02:50+09:00
2021-03-09T00:46:33+09:00 AtCoderで青になりました、というAtCoder色変記事である。 手短に自己紹介 レート推移、各種進捗のグラフ レート推移 AtCoder Problemsの各種進捗状況 解いた問題数×レートのグラフ アルゴリズムのスクールに通ってたので 時系列的なもの。 ライブラリ一覧 pythonで競技プログラミングをやることについて python のいいところ悪いところ いわゆる精進について 全部埋めるのが苦手 AtCoder Problemで自分のレートと同じdiffの問題をやるな ちゃんと理解する ABCとARCのどちらが得意か把握しよう 水色〜青が最近難しすぎる話 今後の目標 競技プログラミン…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a>で青になりました、という<a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a>色変記事である。</p>
<ul class="table-of-contents">
<li><a href="#手短に自己紹介">手短に自己紹介</a></li>
<li><a href="#レート推移各種進捗のグラフ">レート推移、各種進捗のグラフ</a><ul>
<li><a href="#レート推移">レート推移</a></li>
<li><a href="#AtCoder-Problemsの各種進捗状況">AtCoder Problemsの各種進捗状況</a></li>
<li><a href="#解いた問題数レートのグラフ">解いた問題数×レートのグラフ</a></li>
<li><a href="#アルゴリズムのスクールに通ってたので">アルゴリズムのスクールに通ってたので</a></li>
</ul>
</li>
<li><a href="#時系列的なもの">時系列的なもの。</a></li>
<li><a href="#ライブラリ一覧">ライブラリ一覧</a></li>
<li><a href="#pythonで競技プログラミングをやることについて">pythonで競技プログラミングをやることについて</a><ul>
<li><a href="#python-のいいところ悪いところ">python のいいところ悪いところ</a></li>
</ul>
</li>
<li><a href="#いわゆる精進について">いわゆる精進について</a><ul>
<li><a href="#全部埋めるのが苦手">全部埋めるのが苦手</a></li>
<li><a href="#AtCoder-Problemで自分のレートと同じdiffの問題をやるな">AtCoder Problemで自分のレートと同じdiffの問題をやるな</a></li>
<li><a href="#ちゃんと理解する">ちゃんと理解する</a></li>
</ul>
</li>
<li><a href="#ABCとARCのどちらが得意か把握しよう">ABCとARCのどちらが得意か把握しよう</a></li>
<li><a href="#水色青が最近難しすぎる話">水色〜青が最近難しすぎる話</a></li>
<li><a href="#今後の目標">今後の目標</a></li>
<li><a href="#競技プログラミング関係の他の記事">競技プログラミング関係の他の記事</a></li>
</ul>
<h1 id="手短に自己紹介">手短に自己紹介</h1>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a> ID <a href="https://atcoder.jp/users/Linus">Linus</a> で活動している(ハンドル名の由来は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A1%BC%A5%CA%A5%B9%A1%A6%A5%C8%A1%BC%A5%D0%A5%EB%A5%BA">リーナス・トーバルズ</a>ではなく、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%CC%A1%BC%A5%D4%A1%BC">スヌーピー</a>のキャ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%AF">ラク</a>ターであるライナス・ヴァン・ペルトである。)</li>
<li>30代社会人エンジニア(データ分析系)</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>に参加</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Code Jamのみ登録し参加している</li>
<li>得意はその場で色々考察する系。あとDP。</li>
<li>苦手はグラフ全般。</li>
</ul>
<p>ちょっと前は水色で「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>をそこそこしっかりやり込んでいる」と言えた気がするけど、競技人口が増えたせいか青色が目立つようになって、青色がそのポジションになった感がある(個人の感想です)。<br />
あとは「数学が得意なタイプだと、この一つの上の青色に行きますが。(<a href="http://chokudai.hatenablog.com/entry/2019/02/11/155904">AtCoder(競技プログラミング)の色・ランクと実力評価、問題例</a> )」って書かれてたから数学が得意な人間としては青に行っておきたかったのよね。<br />
なので青に上がれて一安心している。</p>
<p>この記事は<br />
<a href="https://adventar.org/calendars/4969">Competitive Programming (1) Advent Calendar 2020 - Adventar</a><br />
の16日目の記事です。</p>
<h1 id="レート推移各種進捗のグラフ">レート推移、各種進捗のグラフ</h1>
<p>色辺記事の定番である。レート推移と、各種進捗のグラフを見てみよう。</p>
<h2 id="レート推移">レート推移</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20201217/20201217002653.png" alt="f:id:soratokimitonoaidani:20201217002653p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>見ての通り、初めて青になったのは2020年3月である。ではなぜこのタイミングで書いているのか? というと、以下のような理由である。<br />
青になる前後で、「青になったら一つの節目として振り返り記事を書こうかな。でも青になって『青色になりました』を書いて、すぐ水色に落ちるのは嫌だな。3回くらい連続で青なら、胸を張って青と言っていいかな」と考えていた。<br />
<strong>そうしたら1回目も2回めも直後で水色に落ちたんだよね!</strong><br />
晴れて今回、2020年11月28日の<a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a> Regular Contest 109で3連続青になったので、自分の考えていた「書くための条件」を満たしたので、
このタイミングで書いているというわけだ。</p>
<h2 id="AtCoder-Problemsの各種進捗状況"><a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a> Problemsの各種進捗状況</h2>
<p>問題を解いている状況を示すために、<a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a> Problemsの画像を色々貼る。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20201217/20201217002935.png" alt="f:id:soratokimitonoaidani:20201217002935p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20201217/20201217002903.png" alt="f:id:soratokimitonoaidani:20201217002903p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20201217/20201217002849.png" alt="f:id:soratokimitonoaidani:20201217002849p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20201217/20201217003039.png" alt="f:id:soratokimitonoaidani:20201217003039p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20201217/20201217003034.png" alt="f:id:soratokimitonoaidani:20201217003034p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>上記だと「何点の問題をどれだけ解いたか」はわからないのね。<br />
というわけで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a> Scoresからもう2枚貼る。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20201217/20201217003647.png" alt="f:id:soratokimitonoaidani:20201217003647p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/soratokimitonoaidani/20201217/20201217003650.png" alt="f:id:soratokimitonoaidani:20201217003650p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h2 id="解いた問題数レートのグラフ">解いた問題数×レートのグラフ</h2>
<p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/atcoder">atcoder</a>でどのくらい精進すれば色が良くなるか気になったので、JPユーザー全員を精進ポイント対レートで2dプロットしました <a href="https://t.co/Mh02IHVLAK">pic.twitter.com/Mh02IHVLAK</a></p>— なぎた (@nagitausu) <a href="https://twitter.com/nagitausu/status/1146753557267222530?ref_src=twsrc%5Etfw">2019年7月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p>
<p>横軸(rated score sum)140000, 縦軸1600を見ると……あれ、成長遅い方(同レーティング内では解いたrated score sumが多い)なのか?</p>
<p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">(鍵RT from <a href="https://twitter.com/e869120?ref_src=twsrc%5Etfw">@e869120</a> )<br>何問解いたら何色になれるか、精密に検証してみたところ、60% の人が達成するラインは、<br><br>青:1120 問<br>黄:1510 問<br>橙:1910 問<br><br>ということが分かりました。また、「1 問解けばレート 1 上がる」という衝撃の事実も判明しました。<br><br>※自由に拡散・使用して良いとのこと <a href="https://t.co/iaOwzFoMeR">pic.twitter.com/iaOwzFoMeR</a></p>— ひゅ〜Men (@men_cotton) <a href="https://twitter.com/men_cotton/status/1218144242238775297?ref_src=twsrc%5Etfw">2020年1月17日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p>
<p>これだと「解いた問題が550問で青以上に上がれるのは30%くらい」なので、解いた問題の割には早めに青を達成できたと自認していたんだけど。</p>
<h2 id="アルゴリズムのスクールに通ってたので"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>のスクールに通ってたので</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%EC%B5%FE%C2%E7%B3%D8">東京大学</a>の工学部計数工学科→情報理工学系数理情報学専攻という経歴であった。
授業の中で計算量とか各種<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>とか叩き込まれるので。
(例えば<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%A4%A5%AF%A5%B9%A5%C8%A5%E9">ダイクストラ</a>やワーシャル・フロイドは授業で扱う。)
あと数学得意系の人生をしていたので。</p>
<blockquote><p>普通に企業とかで超優秀って言ってる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>が居た時に、半分くらいはこのランクになると思います。数学が得意なタイプだと、この一つの上の青色に行きますが。<br />
<a href="http://chokudai.hatenablog.com/entry/2019/02/11/155904">http://chokudai.hatenablog.com/entry/2019/02/11/155904</a></p></blockquote>
<p>数学が得意なタイプなので青に行きたいんじゃ!と思っていた。</p>
<h1 id="時系列的なもの">時系列的なもの。</h1>
<ul>
<li>大学(学部)に在学中、<a href="https://amzn.to/2NpwxlS">ICPCについて書かれた「目指せ!プログラミング世界一―大学対抗プログラミングコンテストICPCへの挑戦」</a>を買って「へーこんなのがあるんだ」と思ったけど、何していいかわからなかったから何もしなかった。</li>
<li>「何をしていいかわからない」から脱出できたのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a>のおかげである。</li>
<li>水色に乗せる。</li>
<li>2018年は何かめんどくさくなって離れた(特に明確な理由はない)</li>
<li>2019年はじめに転職活動して、コーディング面接を受けたときに「やっば、コード書く力が全然無くなってる。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>の実装力を鍛えよう」と思い、競プロに復活した。</li>
<li>2019年7月に前職退職時の有給消化でやり込む</li>
<li>2019年7月にパソコンが壊れて萎える</li>
<li>実家のPCでやってたけど、Kiが解けなくて萎えて離れる</li>
<li>2020年1月に<a class="keyword" href="http://d.hatena.ne.jp/keyword/MacBook%20Pro">MacBook Pro</a>を買い、自由にパソコンが使えるようになり、やり込めるようになった。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>のレートを上げるためには自分用のパソコンを買うのがオススメです(冗談)。</li>
<li>3月に初めて青になるが、次のコンテストで水色に落ちる</li>
<li>5月に再び青になるが、次のコンテストで爆死して水色に落ちる</li>
<li>8〜9月に水色diffや青diffの問題に注力して解く</li>
<li>10月に三たび青になる</li>
</ul>
<h1 id="ライブラリ一覧">ライブラリ一覧</h1>
<p>色変記事を書くときにはとりあえず履修した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>一覧を書けという慣習がありますね。
俺も慣習に倣って書いてみよう。ライブラリのフォルダの中にある<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>は以下の通りである。</p>
<ul>
<li>二項係数(を10<sup>9</sup>+7で割った余り)の計算</li>
<li>Union-Find</li>
<li>整数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%B0%F8%BF%F4%CA%AC%B2%F2">素因数分解</a>関連</li>
<li>二部グラフマッチング</li>
<li>Binary Indexed Tree(BIT)</li>
<li>Longest Increase Subsequence(LIS、最長増加部分列)</li>
<li>ワーシャル・フロイド</li>
</ul>
<p>あと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%FD%CD%A5%C0%E8%C3%B5%BA%F7">幅優先探索</a>・<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%BC%A4%B5%CD%A5%C0%E8%C3%B5%BA%F7">深さ優先探索</a>が出た場合は過去の問題のコードを適当に検索して書き換えて出している(ライブラリにまとめてはいない)。</p>
<p>これらの中で、重要なのは何かと聞かれたらこう答える。</p>
<ul>
<li>二項係数は最重要。特に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>だと、数学的な考察を済ませて「あとは二項係数ライブラリを使ってちょっと書くだけですね」と思っていたら、TLEを起こして泣きを見ることがある。速度が出るライブラリを予め持っておくことを推奨。私が書いた以下の記事を参照→<a href="https://linus-mk.hatenablog.com/entry/2020/02/23/225258">python競技プログラミングで、二項係数の計算でTLEしたので高速化した話 - 子供の落書き帳 Renaissance</a></li>
<li>Union-Findは次に重要。</li>
<li>ぶっちゃけその他はほとんど使わない。(セグメント木を使えないから、使う問題に出会っても「解けない」で終わるため、この感想になるのかもしれない。)</li>
<li>BITとセグメント木は未だによく分かってない。水色のうちに履修しておきなさいという感があるけど、ちゃんと履修しないまま青になってしまった。
<ul>
<li>ABC185のF</li>
</ul>
</li>
<li>あとローリングハッシュやらZ-algorithmやらは何もわからない。</li>
</ul>
<p>習得した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>が、俺の場合は同じ青に上がった人に比べて少ないんだろうなー。<br />
もうちょっと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>を学習して覚えたらもっと強くなれるのかしら。</p>
<h1 id="pythonで競技プログラミングをやることについて"><a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>をやることについて</h1>
<p>私が<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>でやっている理由は、上に書いた方に「まず<a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>の実装力を付けなきゃ」……って言いながら<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>に復活したからである。
なお、それまでは主に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>で書いていた。(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>でふつう使われる「速い言語」を全然使っていない。どんだけ天邪鬼なんだ……)</p>
<h2 id="python-のいいところ悪いところ"><a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a> のいいところ悪いところ</h2>
<p>いいところ</p>
<ul>
<li>変数の型を考慮しなくて良い</li>
<li>オーバーフローを考慮しなくて良い
<ul>
<li>したがって剰余を求めるタイプの問題では、途中での剰余計算が適当でも最後に割って剰余を求めれば良い</li>
<li>100桁の数などを扱うことも可能(計算が重い場合はTLEになるが)</li>
</ul>
</li>
<li>itertoolsのライブラリが便利</li>
</ul>
<p>わるいところ</p>
<ul>
<li>計算量が厳しい</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>の本が基本的に<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>で書いてあるから<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>で書き直さなきゃいけない</li>
</ul>
<p>提出して結果がTLEだったときに、次の行動を考えると以下のいずれかになる。</p>
<ul>
<li>(計算量が想定解よりも遅くてTLEなので)計算量のオーダーを改善する</li>
<li>(計算量には問題がないが、コードが遅くてTLEなので)定数倍高速化する</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>を捨てて<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>(などの速い言語)で書き直す</li>
</ul>
<p>上記のうちどれを選ぶかをミスると痛い目に遭うなぁ、という感覚である。
この間は「解法を思いつく→計算量を見積もる→これ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>だと厳しくね?どうする?どうする?仕方ない、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>で書くか?と書き始める→<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>でうまく書けずに終わる→実は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>でも間に合う」という事があったし(<a href="https://atcoder.jp/contests/arc104/submissions/me?f.Task=&f.LanguageName=&f.Status=&f.User=Linus">ARC104</a>)。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>の場合は、上記3つのうち一番下の選択肢は最初から無い。定数倍高速化が必要になることは絶対にないとは言えないが、かなり稀だろう。<br />
したがって「(計算量が想定解よりも遅くてTLEなので)計算量のオーダーを改善する」と断定してほぼ差し支えないはずだ。迷いがなく次の動きに移れるのが良いなぁと思う。</p>
<h1 id="いわゆる精進について">いわゆる精進について</h1>
<p>精進の定義って何なんだ? 「コンテスト本番中以外に問題を解くこと」で合ってる? みんな当たり前の用に使っているくせに、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>の用語集」みたいな記事を見ても全然意味の説明が出てこないんだが。<br />
それはさておき。</p>
<p>精進のやり方は人によって異なる、合う方法合わない方法があるので、あくまで参考程度にしてください。</p>
<p>コンテスト外で集中して解くのすごい苦手……</p>
<h2 id="全部埋めるのが苦手">全部埋めるのが苦手</h2>
<p>難易度順に下からビッシリ埋めてる人が多いよね。無理です、俺にはできません。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BB%A5%B2%A1%BC">音ゲー</a>もこの傾向がかなり強く「とりあえず当該レベルを1周して全曲触れ」という意見には反発したくなる。<br />
全曲ってそれ何曲あると思ってるの。何クレかかると思ってるの。好きな曲も嫌いな曲もあるのに構わず触れと?<br />
……<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%D7%CF%C3%B5%D9%C2%EA">閑話休題</a>。</p>
<p>初期の問題の質は悪い、とchokudaiさん自ら言ってるし……
<a href="https://twitter.com/chokudai/status/1231612496600944641">https://twitter.com/chokudai/status/1231612496600944641</a></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/AGC">AGC</a>-A、diff 1200〜1299あたりは埋めようと頑張ったが、それでも完全に埋めてはいない。</p>
<h2 id="AtCoder-Problemで自分のレートと同じdiffの問題をやるな"><a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a> Problemで自分のレートと同じdiffの問題をやるな</h2>
<p>自分がレート1500だからといってdiff1500をやろうとするな。もっと下の問題からやれ。</p>
<h2 id="ちゃんと理解する">ちゃんと理解する</h2>
<p>コンテストでは既存の問題と全く同じ問題は(基本的には)出題されない。
したがって、過去の問題を解いたとしても、それをそのまま転用することはできない。
過去の問題から何を得るかが重要になってくる。</p>
<p>ある程度雑でも良いから、方針や感想などを日本語の文章にして書いておくのが大事だ、と最近は考えている。
解法を考えるのに苦労した問題は、日本語で解法を書き留めるようにしている。
最近でちゃんと書いた例だとこの辺りか。</p>
<p><a href="https://github.com/Linus-MK/AtCoder/commit/90388090eb293f762dc681f2687b7dce7d54aaec">https://github.com/Linus-MK/AtCoder/commit/90388090eb293f762dc681f2687b7dce7d54aaec</a><br />
<a href="https://github.com/Linus-MK/AtCoder/commit/8965e87d309b808826ac3d64917b38b6e88f9504">https://github.com/Linus-MK/AtCoder/commit/8965e87d309b808826ac3d64917b38b6e88f9504</a></p>
<p>「どこに気づけばACできたか」というポイントが大事。
具体例を挙げよう。</p>
<p>「連結グラフ一般を対象とした問題は、木に対する問題に帰着できる場合がある」という</p>
<p>紙のノートを作って書いている人もいるけど、私は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%AD%A5%B9%A5%C8%A5%A8%A5%C7%A5%A3%A5%BF">テキストエディタ</a>で書く派である。
(具体的な問題から離れて「今日は××の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>を勉強するわ」という勉強のやり方をすることがほとんど無い。
したがって、学習内容のほとんどは具体的な問題と直接紐付いているので、
基本的に問題を解いたコードにコメントを添えておくのが良いのかなと思っている。
あとは「競プロの教訓の一覧」も作ってますね。全然綺麗にまとめずにメモ程度だけど。</p>
<p><a href="https://github.com/Linus-MK/AtCoder/blob/master/lesson.md">https://github.com/Linus-MK/AtCoder/blob/master/lesson.md</a>
)</p>
<ul>
<li>やったこと
<ul>
<li>問題の解法を抽象化して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B8%C0%B8%EC%B2%BD">言語化</a>しておく</li>
<li>いわゆるメタ解法みたいなやつ</li>
</ul>
</li>
<li>やってないこと
<ul>
<li>バチャ参加</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/CodeForces">CodeForces</a>, yukicoder</li>
</ul>
</li>
</ul>
<h1 id="ABCとARCのどちらが得意か把握しよう">ABCとARCのどちらが得意か把握しよう</h1>
<p>「あなたのレートはどこから?」というサイトがある。<br />
今見たら <a href="https://rating-history.herokuapp.com/rating.html?handle=Linus&number=12">https://rating-history.herokuapp.com/rating.html?handle=Linus&number=12</a> で以下の結果だった。</p>
<pre class="code" data-lang="" data-unlink>All: 111
AGC: -47
ARC: 160
ABC: -134
Other: 132</pre>
<p>このレート帯の人は<a class="keyword" href="http://d.hatena.ne.jp/keyword/AGC">AGC</a>を解くと「A問題が解けない」という事態があり得るので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/AGC">AGC</a>を解いてレートを上げるという選択肢は難しい。
ABCかARCかの二択になると思う。</p>
<p>俺は「問題文はごちゃごちゃ書いてあるけど、要はこういうことでしょ?」をやるのが割と上手いという自覚があるので、ABCよりもARCのほうが得意なのだと思う。
本質的な部分を抽出できるとか、問題文の言い換えができるとか、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%DB%A5%C3%A5%AF">アドホック</a>な力があるとか、その辺かしら?
ABCは1つ躓いただけでレートが大きく下がってしまう感があってヤバい。
あと、ABCに出てる人って、みんな過去問をビッシリ埋めてる人ばかりという印象である。
ABCでは典型力が問われるので、俺のように<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>の学習に抜け漏れがある人がやると、「この問題はセグメント木の典型です」みたいな、俺の履修していない解法のド典型問題が出題されたときに容易に死ぬんだよね。
ARCが復活してからはABCには出ないことにした。そう言っておきながら、気まぐれで出るかもしれないけど。
最近のABCでは、あれもこれも緑diffになりすぎてマジ怖い。</p>
<h1 id="水色青が最近難しすぎる話">水色〜青が最近難しすぎる話</h1>
<ul>
<li>新規参入者の基準レートが下がっているせい
<ul>
<li>これは参考<a class="keyword" href="http://d.hatena.ne.jp/keyword/google">google</a>ドキュメントを探す</li>
</ul>
</li>
<li>上に書いてあった、1問を解いたらレートが1上がるって何なのよ
<ul>
<li>全然上がらないじゃんか</li>
<li>これは予想可能な理由がある</li>
<li>多分なんだけど、このレート帯の他の人はyukicoder, <a class="keyword" href="http://d.hatena.ne.jp/keyword/CodeForces">CodeForces</a>に手を出しているので、見かけ上が「<a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a>を1問解く」であったとしても、実際に解いた問題数、実際の努力量は俺よりも他の人が多いと思われる</li>
</ul>
</li>
<li>どっかで「青になれませんでした」という挫折記事でも出そうかと思っていたら、運良く青に上がれたのでこうして色変記事を書いている</li>
<li>競プロはすべての問題を解決する万能薬ではない
<ul>
<li>数学が強くて、しかも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>を大学で一通りやったわという人(俺)でも、青になるまでにはこの程度の時間と労力をつぎ込む必要がある</li>
<li>時間がある学生ならば良いけど、時間がない人(社会人とか)がやるときには費用対効果を考えたほうが良いと思う</li>
<li>モチベーションが下がったら離れるくらいで良いんじゃないの</li>
<li>少なくとも俺は付かず離れずでやっています</li>
</ul>
</li>
<li>今回の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%D9%A5%F3%A5%C8%A5%AB%A5%EC%A5%F3%A5%C0%A1%BC">アドベントカレンダー</a>にも「なんか水色が厳しくない? 上がれないんだけど?」って記事があるね
<ul>
<li>これ <a href="https://takumat1982.hatenablog.com/entry/2020/12/09/000358">アラフォーが1年以上,緑でうごうごしている話 - 手段としてのソフトウェア</a></li>
</ul>
</li>
</ul>
<h1 id="今後の目標">今後の目標</h1>
<p>青の次は黄色……いや、黄色とか無理だろ。遠すぎるわ。黄色までの真ん中の1800が当座の目標かなぁ。</p>
<p>青は上位7%である。せっかくの休日に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>の大会に出続ける酔狂の中で7%なので、全人類の中では上位1%以内に入っていると思う。</p>
<blockquote><p>組み合わせるのが一番<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%AF">ラク</a>だからです。ある軸で上位3~5%にいるのはそんなに難しくないけど、100万分の1になるのは並大抵のことではないから。かけっこで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A6%A5%B5%A5%A4%A5%F3%A1%A6%A5%DC%A5%EB%A5%C8">ウサイン・ボルト</a>に勝つようなものですよね。だから、20分の1とか、30分の1のレベルで勝てる領域を3つ探すわけです。上位20分1を3つ組み合わせれば、8000分の1の稀少な存在になれる。<br />
<a href="https://diamond.jp/articles/-/208123">https://diamond.jp/articles/-/208123</a></p></blockquote>
<p>このまま努力を続けていって、例えば赤コーダーになれるかって言ったらなれないじゃん。きっと。</p>
<p>この辺で青キープを目指しつつ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%B3%D8%BD%AC">機械学習</a>・データ分析の勉強に少し重心を移すのが正解かなぁと思っている。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCJ">GCJ</a>の予選1回戦突破は自分の中で1つの目標だったけど、2020年に初めて達成できたしなぁ。
ちょっと次の目標が見つからなくて迷子っぽいな。</p>
<p>それでは。</p>
<h1 id="競技プログラミング関係の他の記事"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>関係の他の記事</h1>
<p>こちらもどうぞ。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2F2019%2F06%2F30%2F233405" title="二項係数を10^9+7 で割った余りを求める方法 - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/2019/06/30/233405">linus-mk.hatenablog.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2F2019%2F06%2F16%2F231813" title="累積和を抽象化し、一般の累積演算を考える(累積GCD、累積XOR、他) - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/2019/06/16/231813">linus-mk.hatenablog.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2F2019%2F05%2F26%2F234642" title="pythonの除算結果が浮動小数点数になったので、必要な精度が失われた話 - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/2019/05/26/234642">linus-mk.hatenablog.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2Fpython_competitive_programming_speed_up_1" title="実例から学ぶ Python競技プログラミングの定数倍高速化シリーズ1:徒競走 - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/python_competitive_programming_speed_up_1">linus-mk.hatenablog.com</a></cite></p>
soratokimitonoaidani
effective python 第2版の翻訳改善点 8〜10章
hatenablog://entry/26006613657757797
2020-11-28T00:20:04+09:00
2020-11-28T00:20:04+09:00 オライリー・ジャパンから発売された「Effective Python 第2版 Pythonプログラムを改良する90項目」の日本語訳の改善提案である。気になった箇所について、原文と照らし合わせて問題点を述べ、日本語訳を自分で書き直している。 注意事項 8章 p.289 項目65 p.300 項目68 p.300 項目68 p.309 項目69 9章 p.357 項目78 単純な誤字脱字 関連記事 終わりに 注意事項 「Effective Python 第2版」の日本語版をAmazonで、原著(電子書籍版)をInformIT(ピアソン社の電子書籍販売サイト)で購入した。 以下でそれぞれの本の文章の…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%E9%A5%A4%A5%EA%A1%BC%A1%A6%A5%B8%A5%E3%A5%D1%A5%F3">オライリー・ジャパン</a>から発売された「Effective <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 第2版 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>プログラムを改良する90項目」の日本語訳の改善提案である。気になった箇所について、原文と照らし合わせて問題点を述べ、日本語訳を自分で書き直している。</p>
<p><a href="https://www.amazon.co.jp/Effective-Python-%E2%80%95Python%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E6%94%B9%E8%89%AF%E3%81%99%E3%82%8B90%E9%A0%85%E7%9B%AE-Brett-Slatkin/dp/4873119170/ref=as_li_ss_il?ie=UTF8&linkCode=li3&tag=limk-22&linkId=2a51865e1c1f7f08ba09a29035553721&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4873119170&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=limk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=limk-22&language=ja_JP&l=li3&o=9&a=4873119170" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
<a href="https://www.amazon.co.jp/Effective-Python-Specific-Software-Development/dp/0134853989/ref=as_li_ss_il?_encoding=UTF8&pd_rd_i=0134853989&pd_rd_r=d28c24ba-e01f-4735-af95-e659822ba92e&pd_rd_w=4SXlO&pd_rd_wg=rFVp3&pf_rd_p=4b55d259-ebf0-4306-905a-7762d1b93740&pf_rd_r=DNPBCCHKFVCMJNWN4N36&psc=1&refRID=DNPBCCHKFVCMJNWN4N36&linkCode=li3&tag=limk-22&linkId=454c72d4808babf409499868fb8d156a&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=0134853989&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=limk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=limk-22&language=ja_JP&l=li3&o=9&a=0134853989" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
<ul class="table-of-contents">
<li><a href="#注意事項">注意事項</a></li>
<li><a href="#8章">8章</a><ul>
<li><a href="#p289-項目65">p.289 項目65</a></li>
<li><a href="#p300-項目68">p.300 項目68</a></li>
<li><a href="#p300-項目68-1">p.300 項目68</a></li>
<li><a href="#p309-項目69">p.309 項目69</a></li>
</ul>
</li>
<li><a href="#9章">9章</a><ul>
<li><a href="#p357-項目78">p.357 項目78</a></li>
</ul>
</li>
<li><a href="#単純な誤字脱字">単純な誤字脱字</a></li>
<li><a href="#関連記事">関連記事</a></li>
<li><a href="#終わりに">終わりに</a></li>
</ul>
<h2 id="注意事項">注意事項</h2>
<p>「Effective <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 第2版」の日本語版を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Amazon">Amazon</a>で、原著(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%C5%BB%D2%BD%F1%C0%D2">電子書籍</a>版)をInformIT(ピアソン社の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%C5%BB%D2%BD%F1%C0%D2">電子書籍</a>販売サイト)で購入した。<br />
以下でそれぞれの本の文章の一部を書いているが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C3%F8%BA%EE%B8%A2%CB%A1">著作権法</a>で定められた引用に該当する。
これは訳文の批評のために必要不可欠な引用である。</p>
<ul>
<li>選んだ箇所は私が問題だと思った部分である。文章の意味が間違っているところ(誤訳)と、文意が分かりづらいところとが混じっている。(両者をハッキリ判別するのは難しいので、どの部分がどちらかを示すことはしていない。)</li>
<li>ページ数は日本語版のページ数を示す。原著のページ数は省略した。</li>
<li>「<strong>日本語版</strong>:」のあとに続く部分は「Effective <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 第2版」の日本語版からの引用である。</li>
<li>「<strong>原文</strong>:」のあとに続く部分は「Effective <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>: 90 Specific Ways to Write Better <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> (2nd Edition)」原著からの引用である。</li>
<li>また、「<strong>直訳</strong>」および「<strong>意訳</strong>」は<strong>原文</strong>から私がオリジナルで訳した文である。</li>
<li>「<strong>直訳</strong>」は英語の単語を極力そのまま日本語に置き換えたもの。
<ul>
<li>常に常体である。</li>
<li>「I / you」も訳出している。</li>
<li>高校の授業でやる英文和訳のような結果になるので、日本語として不自然な場合もある。</li>
</ul>
</li>
<li>「<strong>意訳</strong>」はそこから構文の変更などを加えて日本語として整えたものである。
<ul>
<li>常体か敬体かは元の日本語訳と同じとした。</li>
<li>「I / you」は日本語訳と同様、訳出しないことにした。</li>
<li>仮に私が翻訳するとしたら「<strong>意訳</strong>」の文章を最<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%AA%B7%EB">終結</a>果にするであろう。</li>
</ul>
</li>
</ul>
<p>その他、翻訳改善点を書く際に考えたことは以前に書いた1〜3章の記事を参照してほしい。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2Feffecive_python_translation_1" title="effective python 第2版の翻訳改善点 1〜3章 - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/effecive_python_translation_1">linus-mk.hatenablog.com</a></cite></p>
<p>なお、前記事で1〜3章、本記事で8〜10章についてあつかっているので、残りは4〜7章である。
しかし、残りについてまとめる予定は今のところありません。翻訳改善点を書くのは、だいぶ労力がかかるので……。</p>
<h2 id="8章">8章</h2>
<h3 id="p289-項目65">p.289 項目65</h3>
<ul>
<li><strong>日本語版</strong>:else節は、try/exceptの後で起こることは、見た目にも、exceptブロックとは異なるということを保証します。</li>
<li><strong>原文</strong>:The else clause ensures that what follows the try/except is visually distinguished from the except block.</li>
</ul>
<p>「見た目にも……異なる」ってどういうこと?<br />
逐語訳としては間違ってない気がするけど、何が言いたいのかどうにも伝わりにくいような……<br />
主語の「else節」は思い切り無生物主語なので、うまく書き直したいところ。こんなもんでどうだろうか。意訳は2通り書いてみた。</p>
<ul>
<li><strong>直訳</strong>:else節は、try/exceptの後で起こることがexceptブロックと視覚的に区別されていることを保証する。</li>
<li><strong>意訳</strong>:else節を使って書けば、try/exceptの後続の処理を、exceptブロックと見た目にも切り離しておくことができます。</li>
<li><strong>意訳</strong>:else節を使って書けば、try/exceptの後続の処理を、exceptブロックとは別々のものだと見て分かるようになります。</li>
</ul>
<h3 id="p300-項目68">p.300 項目68</h3>
<ul>
<li><strong>日本語版</strong>:pickleの本来の目的は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>オブジェクトを自分がコン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>しているバイナリチャネルでプログラム間をまたいで渡すことです。</li>
<li><strong>原文</strong>:The purpose of pickle is to let you pass <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> objects between programs that you control over binary channels.</li>
<li><strong>直訳</strong>:pickleの目的は、あなたに、あなたが管理するプログラムの間で、バイナリの経路の上で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>オブジェクトを渡させることである。</li>
<li><strong>意訳</strong>:pickleの目的は、自分が管理するプログラムど<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%A6%A4%B7%A4%CE">うしの</a>間で、バイナリの経路を通じて<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>オブジェクトを渡すようにできることです。</li>
</ul>
<p>このすぐ下の文も悪訳。(次項で扱う。)続けざまに悪訳が出てきたんだけど、どうした一体?</p>
<p><strong>日本語版</strong>の翻訳だけど、多分これはcontrolとoverをセットで訳してるよね。
「自分がコン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>しているバイナリチャネル」のあたり。(冷静に考えるとこの訳なら<strong>原文</strong>はbinary channels (that) you controlじゃないとおかしくないか?)<br />
controlが名詞ならそれにoverが結びつくのはよくある。が、今回のcontrolは動詞だ。動詞controlとoverを使う例は辞書でも見つからなかった。<br />
正解は、passとoverがセットになって結びついているのだ。したがってcontrolとoverは意味の上では分かれている。下記に、pass X over Yの形になっている文の例を示す。<br />
channel=経路 をオブジェクトが通っているので、through channelsかin channelsあたりのような気がするが、overが正解なのか……この辺の前置詞の感覚はよく分からないわ。<br />
動詞letについては、ややenableっぽく訳してみた。</p>
<p>参考:<br />
He passed his over his face. 手で顔をなでた<br />
pass one's eye over a letter 手紙に目を通す<br />
(英語活用大辞典より)</p>
<h3 id="p300-項目68-1">p.300 項目68</h3>
<ul>
<li><strong>日本語版</strong>:<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%EA%A5%A2%A5%E9%A5%A4%A5%BA">シリアライズ</a>したデータは、本質的には、元の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>オブジェクトをどのように再構築すればよいかを記述したプログラムを含む。
これは、悪者のpickle情報がデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%EA%A5%A2%A5%E9%A5%A4%A5%BA">シリアライズ</a>しようとする<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>プログラムのどの部分にも忍び込むのに使われうるということを意味する。</li>
<li><strong>原文</strong>:The serialized data contains what is essentially a program that describes how to reconstruct the original <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> object. This means a malicious pickle payload could be used to compromise any part of a <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> program that attempts to deserialize it.</li>
</ul>
<p><strong>日本語版</strong>では「pickle情報が」に対応する述語がどこなのか分かりにくいと思う。</p>
<p>日本語に翻訳するとき、普通は能動態か受動態かで迷ったら能動態で書いたほうが収まりが良いけど、
今回はcompromiseを受動態として訳したほうがスッキリしたのでそうした。<br />
「誰かが不正にアクセスする」という文よりも「システムが不正にアクセスされる」という文を見かけることが多いからかな?</p>
<ul>
<li><strong>直訳</strong>:<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%EA%A5%A2%A5%E9%A5%A4%A5%BA">シリアライズ</a>されたデータは、本質的には元々の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>オブジェクトを再構築する方法を記述したプログラムであるものを含む。
これは、悪意のあるpickle<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A4%A5%ED%A1%BC%A5%C9">ペイロード</a>が、それをデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%EA%A5%A2%A5%E9%A5%A4%A5%BA">シリアライズ</a>しようとする<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>プログラムの任意の部分に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%D4%C0%B5%A5%A2%A5%AF%A5%BB%A5%B9">不正アクセス</a>するのに使われる可能性があるということを意味する。</li>
<li><strong>意訳</strong>:<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%EA%A5%A2%A5%E9%A5%A4%A5%BA">シリアライズ</a>されたデータには、元々の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>オブジェクトを再構築する方法を記述したプログラムと同等のものが含まれている。
したがって、悪意のあるpickle<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A4%A5%ED%A1%BC%A5%C9">ペイロード</a>があると、それをデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%EA%A5%A2%A5%E9%A5%A4%A5%BA">シリアライズ</a>しようとする<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>プログラムの任意の部分が不正にアクセスされてしまう可能性がある。</li>
</ul>
<h3 id="p309-項目69">p.309 項目69</h3>
<ul>
<li><strong>日本語版</strong>:Decimalクラスでは、丸めのための組み込み関数があり、望ましい丸め操作を正確に必要な桁数で丸めてくれます。これで、抱えていた切り上げ問題が解決されます。</li>
<li><strong>原文</strong>:Luckily, the Decimal class has a built-in function for rounding to exactly the decimal place needed with the desired rounding behavior. This works for the higher cost case from earlier:</li>
</ul>
<p>「丸め操作を……丸めてくれます」ってどういうことよ。「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C7%CF%A4%AB%A4%E9%CD%EE%C7%CF">馬から落馬</a>する」とか「頭痛が痛い」と同様にダメだと思うんだけど。</p>
<ul>
<li><strong>直訳</strong>:幸運なことに、Decimalクラスは、所望の丸め挙動によって10進法地点へ正確に丸める操作のための組み込み関数を持つ。これは、始めにあったより高い料金の例でもうまくいく。</li>
<li><strong>意訳</strong>:幸いにもDecimalクラスには組み込み関数があり、希望どおりの丸め方で数値を10進法の数値に正確に丸めることができます。これは、始めに挙げたより高い料金の例でもうまくいきます。</li>
</ul>
<p>rounding to exactly the decimal place(<strong>原文</strong>)と<br />
rounding to the exact decimal placeの違いって何なんだ……exactlyがroundingを修飾するならtoの前になるんじゃないか……分からないや。</p>
<p>なおおまけの指摘だが、この項目69でずっと小数点2桁で四捨五入/切り上げをしているのはセント単位にしたいからである。<br />
<strong>原文</strong>では「round to the nearest whole cent」つまり「最も近い、セント単位の数に丸める」という意味である。
「round ~ to the nearest whole number 小数点第1位で四捨五入して整数にする」が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%D1%BC%AD%CF%BA">英辞郎</a>にあったので、numberの代わりにcentが入った形だろう。
何でwholeなのかcentが単数なのかよく分からんけど。<br />
英文にあった「セント」が日本語版では完全に消えている。
「最も近い整数への丸め方式(p.308 上部)」じゃ意味が通らないだろう。だって四捨五入の結果である5.36は整数じゃないんだから。</p>
<h2 id="9章">9章</h2>
<h3 id="p357-項目78">p.357 項目78</h3>
<ul>
<li><strong>日本語版</strong>:厳密には、どのdatabaseオブジェクトでも取れるように、一部の引数が使えるのであれば、定数unittest.mock.ANYを、どんな引数でも取れることを示す値として使います。</li>
<li><strong>原文</strong>:If I actually don’t care about some of the individual parameters, such as exactly which database object was used, then I can indicate that any <a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a> is okay for an argument by using the unittest.mock.ANY constant.</li>
</ul>
<p>「individual parameters」つまり個々のパラメータの一部の例として、「exactly which database object was used」=「正確にどのdatabaseオブジェクトが使われたのか」がある。日本語版では、exactlyに相当する「厳密には」が変なところにあるし、文意がよく分からない。<br />
挿入句がちょっと訳しづらい。カッコに入れるくらいしか上手いやり方が思いつかない。以下のようになる。</p>
<ul>
<li><strong>直訳</strong>:もし実際には私が個々のパラメータの一部(例えば「正確にどのdatabaseオブジェクトが使われたのか」など)には関心がないのであれば、私はunittest.mock.ANYという定数を使うことで、その変数にはどんな値でも大丈夫であることを示すことができる。</li>
<li><strong>意訳</strong>:もし実際には個々のパラメータの一部(例えば「正確にどのdatabaseオブジェクトが使われたのか」など)が重要でないのならば、unittest.mock.ANYという定数を使って、その変数にはどんな値を入れても構わないことを示すことができます。</li>
</ul>
<h2 id="単純な誤字脱字">単純な誤字脱字</h2>
<p>気づいた範囲で書いておきます。</p>
<p>p.343<br />
実際の型とか構成部分がはっきりしていなことです。<br />
→<br />
実際の型とか構成部分がはっきりしていないことです。</p>
<p>p.348<br />
try/excep 文とよく似ていて、<br />
→<br />
try/except 文とよく似ていて、</p>
<p>p.356 (ページ中央のAtributeErrorのすぐ下)<br />
daabase引数にはobjectを使います。<br />
→<br />
database引数にはobjectを使います。</p>
<h2 id="関連記事">関連記事</h2>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2Feffecive_python_translation_1" title="effective python 第2版の翻訳改善点 1〜3章 - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/effecive_python_translation_1">linus-mk.hatenablog.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2F2019%2F10%2F27%2F235143" title="Effective Python 第2版(原著)が出るみたいだよ - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/2019/10/27/235143">linus-mk.hatenablog.com</a></cite></p>
<h2 id="終わりに">終わりに</h2>
<p>目についたところを挙げた。しかし、すべて完全に読んだわけではないので、まだ見逃しているところがあると思う。
「Effective <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>のこの部分の文章の意味がよくわからないんだけど!」というのがあれば、コメント欄とか<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>で言ってくれれば見てみます。この記事に加筆するかもしれません。</p>
soratokimitonoaidani
実例から学ぶ Python競技プログラミングの定数倍高速化シリーズ1:徒競走
hatenablog://entry/26006613646317226
2020-10-28T22:58:28+09:00
2020-10-28T23:20:25+09:00 競技プログラミングのAtCoderの問題をPythonを使って解き、定数倍高速化した結果をまとめる。 定数倍高速化とは何か 注意事項 解法 処理時間まとめ 最初 高速化(1) 早期break 高速化(2) 計算量の削減 /(1)を上書き 高速化(3) 入力 input = sys.stdin.readline 高速化(4) 真偽値判定を簡略化 高速化(5) 2**nを1<<nに変更 高速化(6) indexをsetで管理する /(4)(5)を上書き まとめ 定数倍高速化とは何か 定数倍高速化 - MonoBook より 定数倍高速化とは、アルゴリズムの改善による高速化とは違い、計算処理の方法を…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/AtCoder">AtCoder</a>の問題を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>を使って解き、定数倍高速化した結果をまとめる。</p>
<ul class="table-of-contents">
<li><a href="#定数倍高速化とは何か">定数倍高速化とは何か</a></li>
<li><a href="#注意事項">注意事項</a></li>
<li><a href="#解法">解法</a></li>
<li><a href="#処理時間まとめ">処理時間まとめ</a></li>
<li><a href="#最初">最初</a></li>
<li><a href="#高速化1-早期break">高速化(1) 早期break</a></li>
<li><a href="#高速化2-計算量の削減-1を上書き">高速化(2) 計算量の削減 /(1)を上書き</a></li>
<li><a href="#高速化3-入力-input--sysstdinreadline">高速化(3) 入力 input = sys.stdin.readline</a></li>
<li><a href="#高速化4-真偽値判定を簡略化">高速化(4) 真偽値判定を簡略化</a></li>
<li><a href="#高速化5-2nを1nに変更">高速化(5) 2**nを1<<nに変更</a></li>
<li><a href="#高速化6-indexをsetで管理する-45を上書き">高速化(6) indexをsetで管理する /(4)(5)を上書き</a></li>
<li><a href="#まとめ">まとめ</a></li>
</ul>
<h2 id="定数倍高速化とは何か">定数倍高速化とは何か</h2>
<p><a href="https://monobook.org/wiki/%E5%AE%9A%E6%95%B0%E5%80%8D%E9%AB%98%E9%80%9F%E5%8C%96">定数倍高速化 - MonoBook</a> より</p>
<blockquote><p>定数倍高速化とは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>の改善による高速化とは違い、計算処理の方法を改善することにより計算量のオーダーを変えずに処理を高速化することである。</p></blockquote>
<p>そしてこの記事では、一般論ではなく、具体的な問題に対する最適化を取り上げる。つまり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>の特定の問題を色々なコードで解いてみて、その結果を整理してそこから教訓を得ようというものだ。</p>
<p>(初回なのにタイトルに「シリーズ」とか入れてるけど、大丈夫なんだろうか。私が記事を書くやる気が続くだろうか……?)</p>
<p>今回取り上げるのは、<a href="https://atcoder.jp/contests/abc041/tasks/abc041_d">AtCoder Beginner Contest 041 D問題 徒競走</a>である。</p>
<h2 id="注意事項">注意事項</h2>
<p>本検証は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 3.8.2に言語がバージョンアップされた後に実施している。<br />
そのため、処理時間は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 3.8.2, PyPy3 (7.3.0)である。</p>
<p>処理時間は1回提出した結果であり、複数回の平均ではない。</p>
<h2 id="解法">解法</h2>
<p>解法の細かい説明はしない。そこはこの記事の主眼ではないので。<br />
というか、解説を読んで解法を理解してからACしたので、解法は公式解説PDFと全く同じである。</p>
<h2 id="処理時間まとめ">処理時間まとめ</h2>
<p>以下の表は、Python3 / PyPy3の処理時間をまとめたものである。最初のコードから始めて、高速化を順次実行したときの、実行時間である。<a href="#f-70795ff7" name="fn-70795ff7" title="余談になるが、markdownで表を作るの面倒だなぁと探したら以下のWebツールが見つかった。「MarkdownテーブルをExcelライクな操作で簡単に作成できるツールです」と書いてある。便利。
[https://notepm.jp/markdown-table-tool] ">*1</a></p>
<table>
<thead>
<tr>
<th> コード </th>
<th style="text-align:right;"> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> (3.8.2) </th>
<th style="text-align:right;"> PyPy3 (7.3.0) </th>
</tr>
</thead>
<tbody>
<tr>
<td> 最初 </td>
<td style="text-align:right;"> TLE </td>
<td style="text-align:right;"> 750ms </td>
</tr>
<tr>
<td> 高速化(1) 早期break </td>
<td style="text-align:right;"> TLE </td>
<td style="text-align:right;"> 324ms </td>
</tr>
<tr>
<td> 高速化(2) 計算量の削減 </td>
<td style="text-align:right;"> TLE </td>
<td style="text-align:right;"> 243ms </td>
</tr>
<tr>
<td> 高速化(3) sys.stdin.readline </td>
<td style="text-align:right;"> TLE </td>
<td style="text-align:right;"> 230ms </td>
</tr>
<tr>
<td> 高速化(4) 真偽値判定を簡略化 </td>
<td style="text-align:right;"> TLE(3262ms) </td>
<td style="text-align:right;"> 230ms </td>
</tr>
<tr>
<td> 高速化(5) 2**nを1<<nに変更 </td>
<td style="text-align:right;"> 1626ms </td>
<td style="text-align:right;"> 169ms </td>
</tr>
<tr>
<td> 高速化(6) indexをsetで管理 </td>
<td style="text-align:right;"> 1032ms </td>
<td style="text-align:right;"> 270ms </td>
</tr>
</tbody>
</table>
<h2 id="最初">最初</h2>
<p><a href="https://github.com/Linus-MK/AtCoder/commit/a972c5ef840ba1cb2ba1bd6309b498805708140f">最初の提出コード:GitHub</a><br />
<a href="https://atcoder.jp/contests/abc041/submissions/17692803">最初の提出結果:AtCoder</a></p>
<p>正直、提出したときはPyPyでも通らないだろうと思っていた。
「これは計算量を落とせる(後述の高速化(2)のこと)のに、わざわざ計算量が大きい解法で解いているので、おそらくTLEになるだろう。でも一応提出してみるか」と思っていたら通ってしまった。<br />
計算量は外側のループから順に、2<sup>n</sup> * n * mである。最大値を代入すると、
<code>2^16 * 16 * (16*15)/ 2 = 125829120</code><br />
あれ1億2500万だぞ……!? しかもこのコードは途中でbreakしないから、ループが全部回るぞ……何で通ったの???</p>
<p>一応ACは取れたので良いのだが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>でも通るようにできないかと思って、色々と定数倍高速化を試みた。<br />
なお<strong>この問題の制限時間は3秒である。</strong></p>
<h2 id="高速化1-早期break">高速化(1) 早期break</h2>
<p><a href="https://github.com/Linus-MK/AtCoder/commit/97c4202b3140475bd904da0fa492aa4ad30cd2f8">コード差分:GitHub</a></p>
<p>とりあえずパッと思いつくものを入れた。
フラグを最初にTrueにしておいて、どれか一つでも条件を満たすならFalseになるというパターンのコードである。だから、Falseとわかった時点でその後の計算は不要であり、ループをbreakできる。</p>
<p>計算量は……えーっとどうなるんだ。
最悪のケースになる入力は、多分以下の場合だろう。</p>
<pre class="code" data-lang="" data-unlink>16 120
1 2
1 3
2 3
1 4
2 4
3 4
1 5
……(後略)</pre>
<p>そうすると、</p>
<ul>
<li>頂点2が1位になりえないのは、1個目の辺を見た段階でわかる(のでここでbreak)</li>
<li>頂点3が1位になりえないのは、2個目の辺を見た段階でわかる(のでここでbreak)</li>
<li>頂点4が1位になりえないのは、4個目の辺を見た段階でわかる(のでここでbreak)</li>
</ul>
<p>……というふうに、各頂点に対する辺のループの数は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%B0%B3%D1%BF%F4">三角数</a>+1になる。毎回120個すべてを見ていた場合と比べて、計算量は大雑把に3分の1かな。多分。<br />
(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%B0%B3%D1%BF%F4">三角数</a>はxの2次関数なので、x<sup>2</sup>を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%E8%B4%D6">区間</a>[0,1]で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%D1%CA%AC">積分</a>するイメージである)</p>
<p>PyPyの実行時間では半分以下と著しく速くなっているが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>では依然としてTLEである。</p>
<h2 id="高速化2-計算量の削減-1を上書き">高速化(2) 計算量の削減 /(1)を上書き</h2>
<p><a href="https://github.com/Linus-MK/AtCoder/commit/11402fcd9e560c30600eefc637151c8b9bfcb91a">コード差分:GitHub</a></p>
<p>定数倍高速化と散々言ってるが、<strong>ここだけは計算量の式が変わる高速化です(=定数倍高速化ではない)。</strong><br />
<code>may_be_first</code>(1位になる可能性があるか否か)を最初にまとめて計算しておけば、繰り返し計算する必要はない。<br />
計算量が2<sup>n</sup> * n * m → 2<sup>n</sup> * (n + m) に削減された。<br />
数字の上では 1億2500万→891万 で10分の1以下になってるけど、PyPyの時間はそこまで短くなってはいない。なんでやろ。</p>
<h2 id="高速化3-入力-input--sysstdinreadline">高速化(3) 入力 input = sys.stdin.readline</h2>
<p><a href="https://github.com/Linus-MK/AtCoder/commit/81e6c1fc032670181e3451a5f8af2d0e7d205bca">コード差分:GitHub</a></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B6%A5%B5%BB%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">競技プログラミング</a>をするならまずやろうと言われる<code>input = sys.stdin.readline</code>。<br />
簡単にできるから入れてみたものの、あまり変化なし。<br />
(これのおかげでTLEが消えて無事に通ったという経験がない。個人的にはあまり効果を感じていないので、普段は<code>input = sys.stdin.readline</code>を書いていない。まぁ、今回は入力が最大でも121行だから、入力を高速化しても効果が殆ど無いのだろう。)</p>
<h2 id="高速化4-真偽値判定を簡略化">高速化(4) 真偽値判定を簡略化</h2>
<p><a href="https://github.com/Linus-MK/AtCoder/commit/939eba3ed8a0dd01b34b80abac1383c8a74ecec0">コード差分:GitHub</a></p>
<p>bit AND を取った結果が0か非0かを判定するために<code>x & y > 0</code>と書いていたが、0より大きいか小さいか判定する必要はないので単に<code>x & y</code>でよい。</p>
<p>TLEのとき、表示されている時間は本当にかかった時間とは限らない。制限時間を少し過ぎたところでコードを強制終了している。<br />
1つ前までは、3.3秒あたりで強制終了しているようにみえる(<strong>本当のところは不明です</strong>)。
しかし今回は3262msである。<br />
つまり今までは3.3秒を過ぎて強制終了されたが、
今回は3.262秒で計算が終わったが、それが3秒より大きいのでTLEであると推測される(<strong>本当のところは不明です</strong>)。<br />
あと一息だ。</p>
<h2 id="高速化5-2nを1nに変更">高速化(5) 2**nを1<<nに変更</h2>
<p><a href="https://github.com/Linus-MK/AtCoder/commit/87ccd0abab6bba01b8f192c471fd672e52aa4e41">コード差分:GitHub</a></p>
<p>ついに<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>でも</p>
<p>俺の中では「<code>2**n</code>と書こうが<code>1<<n</code>と書こうが同じじゃん」と思ってたけど、
3262ms→1626msだ! 時間がなんと半分以下になった!!<br />
(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>の最適化で勝手に書き換えられるかなと思っていたけど、最適化は走らないんだね……一般の<code>a**n</code>の場合はこの書き換えは使えない。だから、冷静に考えたら、一部の数のときだけ適用できる書き換えをするのは難しいんだろうな……)</p>
<p><strong>マジかよ。累乗計算をビット演算に変えるだけでこんなに変わるの!?</strong></p>
<p>特定桁のbit ANDを取るとき、つい癖で<code>if x & 2**digit > 0</code>と書いていたけど、これがそれほどまでに動作の遅い書き方だとは知らなかった。</p>
<h2 id="高速化6-indexをsetで管理する-45を上書き">高速化(6) indexをsetで管理する /(4)(5)を上書き</h2>
<p><a href="https://github.com/Linus-MK/AtCoder/commit/3500ea5ab58037a3f7281b824433e8d737a43fc1">コード差分:GitHub</a></p>
<p>idxと特定桁のbit ANDを取る処理を何度かやっている。<br />
「これ……どの桁にビットが立っているかを最初に集合(set)に入れて、あとはdigitが集合に含まれるか判定するほうが速いかもしれない?」と考えた。<br />
ここの集合の作り方はリスト内包表記で簡潔に書くと動作が速い。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>だと1626→1032msと速くなった。<br />
一方で、PyPyだと169ms→270msと逆に遅くなった。PyPyだと時間がかかる処理なんだろうか。</p>
<h2 id="まとめ">まとめ</h2>
<p><b><code>2**n</code> は非常に遅い書き方なので <code>1<<n</code> にしましょう。
</b></p>
<p>ただし<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の優先順位には注意!!<br />
今回も<code>2**n</code> を <code>1<<n</code> に置換した後、確認せずにsubmitして、Runtime Errorを1回出した。<br />
<code>idx - (1<<digit)</code>とすべきところで<code>idx - 1<<digit</code>と書いて、減算を最初に計算してしまったからである。<br />
以前も同じミスにハマって、そのときに書いた記事が以下である。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2F2019%2F05%2F05%2F210000" title="Python ビットシフトと加減算の演算子の優先順位 - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/2019/05/05/210000">linus-mk.hatenablog.com</a></cite></p>
<p>それでは。</p>
<div class="footnote">
<p class="footnote"><a href="#fn-70795ff7" name="f-70795ff7" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">余談になるが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/markdown">markdown</a>で表を作るの面倒だなぁと探したら以下のWebツールが見つかった。「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Markdown">Markdown</a>テーブルを<a class="keyword" href="http://d.hatena.ne.jp/keyword/Excel">Excel</a>ライクな操作で簡単に作成できるツールです」と書いてある。便利。
<a href="https://notepm.jp/markdown-table-tool">https://notepm.jp/markdown-table-tool</a> </span></p>
</div>
soratokimitonoaidani
pandasでDataFrameのセルにlistを代入する
hatenablog://entry/26006613645328698
2020-10-26T12:55:54+09:00
2020-10-26T12:55:54+09:00 pandasのDataFrameのセル(1つのマス)にpythonのリスト(配列)を代入しようとして、苦労したのでやり方をまとめておく。 (pandasの公式ドキュメントではセルをcellとは呼ばず、valueもしくはscalar valueと呼んでいるようだ。) 注意 準備 失敗例 loc, ilocだとエラーになる DataFrameのセルにlistを代入するためには、at, iatを使う 数値の列にリストを入れたい 参考文献 注意 おそらく、DataFrameのセルにlistを入れようとするのはあまり良い方法ではない。 この使い方を、pandas側があまり想定していないような気がする。 …
<p>pandasのDataFrameのセル(1つのマス)に<a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>のリスト(配列)を代入しようとして、苦労したのでやり方をまとめておく。<br />
(pandasの公式ドキュメントではセルをcellとは呼ばず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>もしくはscalar <a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>と呼んでいるようだ。)</p>
<ul class="table-of-contents">
<li><a href="#注意">注意</a></li>
<li><a href="#準備">準備</a></li>
<li><a href="#失敗例-loc-ilocだとエラーになる">失敗例 loc, ilocだとエラーになる</a></li>
<li><a href="#DataFrameのセルにlistを代入するためにはat-iatを使う">DataFrameのセルにlistを代入するためには、at, iatを使う</a></li>
<li><a href="#数値の列にリストを入れたい">数値の列にリストを入れたい</a></li>
<li><a href="#参考文献">参考文献</a></li>
</ul>
<h2 id="注意">注意</h2>
<p>おそらく、DataFrameのセルにlistを入れようとするのは<strong>あまり良い方法ではない</strong>。
この使い方を、pandas側があまり想定していないような気がする。<br />
私がDataFrameのセルにlistを持たせたときは、色々な処理がいちいちうまく行かないので、少しやってみたけどやめてしまった。<br />
結局データの持ち方を変えて、やりたい分析を実施した。<br />
データの持ち方を変えて別の方法でできないか検討したほうが良いだろう。</p>
<h2 id="準備">準備</h2>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd
<span class="synPreProc">import</span> numpy <span class="synStatement">as</span> np
pd.options.display.notebook_repr_html = <span class="synIdentifier">False</span> <span class="synComment"># jupyter notebook上での出力形式を制御するために書いています。無くても動きます。</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 動作環境の確認</span>
<span class="synIdentifier">print</span>(pd.__version__)
<span class="synIdentifier">print</span>(np.__version__)
<span class="synComment"># --------------------</span>
<span class="synConstant">1.1</span>.<span class="synConstant">2</span>
<span class="synConstant">1.19</span>.<span class="synConstant">1</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df = pd.DataFrame({
<span class="synConstant">'col_A'</span>: [<span class="synConstant">1.2</span> ,<span class="synConstant">3.4</span>, <span class="synConstant">5.6</span>],
<span class="synConstant">'col_B'</span>: [<span class="synConstant">9.8</span>, <span class="synConstant">7.6</span>, <span class="synConstant">5.4</span>],
<span class="synConstant">'col_string'</span>: [<span class="synConstant">'hello'</span>, <span class="synConstant">'good_morning'</span>, <span class="synConstant">'good_night'</span>]
})
df
<span class="synComment"># --------------------</span>
col_A col_B col_string
<span class="synConstant">0</span> <span class="synConstant">1.2</span> <span class="synConstant">9.8</span> hello
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7.6</span> good_morning
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5.4</span> good_night
</pre>
<h2 id="失敗例-loc-ilocだとエラーになる">失敗例 loc, ilocだとエラーになる</h2>
<p>上記のdfの一番右下、「good_night」と書いてあるところにリストを代入したいとしよう。<br />
<code>loc</code>や<code>iloc</code>を使ってやろうとするとエラーになる。<br />
(pandasのバージョンによっては別のエラーメッセージになるかもしれない)</p>
<pre class="code lang-python" data-lang="python" data-unlink>my_list = [<span class="synConstant">'this'</span> , <span class="synConstant">'is'</span>, <span class="synConstant">'a'</span>, <span class="synConstant">'list'</span>]
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">print</span>(df.loc[<span class="synConstant">2</span>, <span class="synConstant">'col_string'</span>])
df.loc[<span class="synConstant">2</span>, <span class="synConstant">'col_string'</span>] = my_list
<span class="synComment"># --------------------</span>
good_night
---------------------------------------------------------------------------
<span class="synType">ValueError</span> Traceback (most recent call last)
<ipython-<span class="synIdentifier">input</span>-<span class="synConstant">5</span>-4bd9c63f53aa> <span class="synStatement">in</span> <module>
<span class="synConstant">1</span> <span class="synIdentifier">print</span>(df.loc[<span class="synConstant">2</span>, <span class="synConstant">'col_string'</span>])
----> <span class="synConstant">2</span> df.loc[<span class="synConstant">2</span>, <span class="synConstant">'col_string'</span>] = my_list
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/pandas/core/indexing.py <span class="synStatement">in</span> __setitem__(self, key, value)
<span class="synConstant">668</span>
<span class="synConstant">669</span> iloc = self <span class="synStatement">if</span> self.name == <span class="synConstant">"iloc"</span> <span class="synStatement">else</span> self.obj.iloc
--> <span class="synConstant">670</span> iloc._setitem_with_indexer(indexer, value)
<span class="synConstant">671</span>
<span class="synConstant">672</span> <span class="synStatement">def</span> <span class="synIdentifier">_validate_key</span>(self, key, axis: <span class="synIdentifier">int</span>):
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/pandas/core/indexing.py <span class="synStatement">in</span> _setitem_with_indexer(self, indexer, value)
<span class="synConstant">1664</span> <span class="synStatement">if</span> is_list_like_indexer(value) <span class="synStatement">and</span> <span class="synConstant">0</span> != lplane_indexer != <span class="synIdentifier">len</span>(value):
<span class="synConstant">1665</span> <span class="synComment"># Exclude zero-len for e.g. boolean masking that is all-false</span>
-> <span class="synConstant">1666</span> <span class="synStatement">raise</span> <span class="synType">ValueError</span>(
<span class="synConstant">1667</span> <span class="synConstant">"cannot set using a multi-index "</span>
<span class="synConstant">1668</span> <span class="synConstant">"selection indexer with a different "</span>
<span class="synType">ValueError</span>: cannot <span class="synIdentifier">set</span> using a multi-index selection indexer <span class="synStatement">with</span> a different length than the value
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">print</span>(df.iloc[<span class="synConstant">2</span>, <span class="synConstant">2</span>])
df.iloc[<span class="synConstant">2</span>, <span class="synConstant">2</span>] = my_list
<span class="synComment"># --------------------</span>
good_night
---------------------------------------------------------------------------
<span class="synType">ValueError</span> Traceback (most recent call last)
<ipython-<span class="synIdentifier">input</span>-<span class="synConstant">6</span>-dd2da9191db9> <span class="synStatement">in</span> <module>
<span class="synConstant">1</span> <span class="synIdentifier">print</span>(df.iloc[<span class="synConstant">2</span>, <span class="synConstant">2</span>])
----> <span class="synConstant">2</span> df.iloc[<span class="synConstant">2</span>, <span class="synConstant">2</span>] = my_list
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/pandas/core/indexing.py <span class="synStatement">in</span> __setitem__(self, key, value)
<span class="synConstant">668</span>
<span class="synConstant">669</span> iloc = self <span class="synStatement">if</span> self.name == <span class="synConstant">"iloc"</span> <span class="synStatement">else</span> self.obj.iloc
--> <span class="synConstant">670</span> iloc._setitem_with_indexer(indexer, value)
<span class="synConstant">671</span>
<span class="synConstant">672</span> <span class="synStatement">def</span> <span class="synIdentifier">_validate_key</span>(self, key, axis: <span class="synIdentifier">int</span>):
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/pandas/core/indexing.py <span class="synStatement">in</span> _setitem_with_indexer(self, indexer, value)
<span class="synConstant">1664</span> <span class="synStatement">if</span> is_list_like_indexer(value) <span class="synStatement">and</span> <span class="synConstant">0</span> != lplane_indexer != <span class="synIdentifier">len</span>(value):
<span class="synConstant">1665</span> <span class="synComment"># Exclude zero-len for e.g. boolean masking that is all-false</span>
-> <span class="synConstant">1666</span> <span class="synStatement">raise</span> <span class="synType">ValueError</span>(
<span class="synConstant">1667</span> <span class="synConstant">"cannot set using a multi-index "</span>
<span class="synConstant">1668</span> <span class="synConstant">"selection indexer with a different "</span>
<span class="synType">ValueError</span>: cannot <span class="synIdentifier">set</span> using a multi-index selection indexer <span class="synStatement">with</span> a different length than the value
</pre>
<h2 id="DataFrameのセルにlistを代入するためにはat-iatを使う">DataFrameのセルにlistを代入するためには、at, iatを使う</h2>
<p><code>loc</code>や<code>iloc</code>は複数のセルを選択することもできるので、右辺が配列だと「え?これ複数のセルに代入したいんじゃないの? 左辺が単一のセルなのに右辺がセル4つ分の値なんだから、これじゃダメだよ」とpandasが勘違いするんだろう。たぶん。<br />
pandasには必ず一つのセルを選択する(複数のセルを選択できない)関数がある。<code>at</code>と<code>iat</code>だ。これを使うとセルにlistを代入できる。</p>
<p><code>at</code>を使った例。<code>loc</code>と同様に、行と列の名前で位置を指定する。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">print</span>(df.at[<span class="synConstant">2</span>, <span class="synConstant">'col_string'</span>])
df.at[<span class="synConstant">2</span>, <span class="synConstant">'col_string'</span>] = my_list
<span class="synComment"># --------------------</span>
good_night
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">print</span>(df)
<span class="synIdentifier">print</span>(<span class="synConstant">'...'</span>)
<span class="synIdentifier">print</span>(df.loc[<span class="synConstant">2</span>, <span class="synConstant">'col_string'</span>])
<span class="synIdentifier">print</span>(<span class="synIdentifier">type</span>(df.loc[<span class="synConstant">2</span>, <span class="synConstant">'col_string'</span>]))
<span class="synComment"># --------------------</span>
col_A col_B col_string
<span class="synConstant">0</span> <span class="synConstant">1.2</span> <span class="synConstant">9.8</span> hello
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7.6</span> good_morning
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5.4</span> [this, <span class="synStatement">is</span>, a, <span class="synIdentifier">list</span>]
...
[<span class="synConstant">'this'</span>, <span class="synConstant">'is'</span>, <span class="synConstant">'a'</span>, <span class="synConstant">'list'</span>]
<<span class="synStatement">class</span> <span class="synConstant">'list'</span>>
</pre>
<p><code>iat</code>を使った例。<code>iloc</code>と同様に、行と列の番号(何行目・何列目)で位置を指定する。</p>
<pre class="code lang-python" data-lang="python" data-unlink>my_list = [<span class="synConstant">'another'</span>, <span class="synConstant">'list'</span>]
<span class="synIdentifier">print</span>(df.iat[<span class="synConstant">0</span>, <span class="synConstant">2</span>])
df.iat[<span class="synConstant">0</span>, <span class="synConstant">2</span>] = my_list
<span class="synComment"># --------------------</span>
hello
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">print</span>(df)
<span class="synIdentifier">print</span>(<span class="synConstant">'...'</span>)
<span class="synIdentifier">print</span>(df.iloc[<span class="synConstant">0</span>, <span class="synConstant">2</span>])
<span class="synIdentifier">print</span>(<span class="synIdentifier">type</span>(df.iloc[<span class="synConstant">0</span>, <span class="synConstant">2</span>]))
<span class="synComment"># --------------------</span>
col_A col_B col_string
<span class="synConstant">0</span> <span class="synConstant">1.2</span> <span class="synConstant">9.8</span> [another, <span class="synIdentifier">list</span>]
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7.6</span> good_morning
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5.4</span> [this, <span class="synStatement">is</span>, a, <span class="synIdentifier">list</span>]
...
[<span class="synConstant">'another'</span>, <span class="synConstant">'list'</span>]
<<span class="synStatement">class</span> <span class="synConstant">'list'</span>>
</pre>
<h2 id="数値の列にリストを入れたい">数値の列にリストを入れたい</h2>
<p>ここまではうまく行った。しかし、数値の入っている列のセルにリストを代入しようとするとエラーが生じる。</p>
<pre class="code lang-python" data-lang="python" data-unlink>my_list = [<span class="synConstant">3</span>, <span class="synConstant">4</span>, <span class="synConstant">5</span>]
<span class="synIdentifier">print</span>(df.at[<span class="synConstant">0</span>, <span class="synConstant">'col_A'</span>])
df.at[<span class="synConstant">0</span>, <span class="synConstant">'col_A'</span>] = my_list
<span class="synComment"># --------------------</span>
<span class="synConstant">1.2</span>
---------------------------------------------------------------------------
<span class="synType">TypeError</span> Traceback (most recent call last)
<span class="synType">TypeError</span>: <span class="synIdentifier">float</span>() argument must be a string <span class="synStatement">or</span> a number, <span class="synStatement">not</span> <span class="synConstant">'list'</span>
The above exception was the direct cause of the following exception:
<span class="synType">ValueError</span> Traceback (most recent call last)
<ipython-<span class="synIdentifier">input</span>-<span class="synConstant">12</span>-02f17b50862e> <span class="synStatement">in</span> <module>
<span class="synConstant">1</span> my_list = [<span class="synConstant">3</span>, <span class="synConstant">4</span>, <span class="synConstant">5</span>]
<span class="synConstant">2</span> <span class="synIdentifier">print</span>(df.at[<span class="synConstant">0</span>, <span class="synConstant">'col_A'</span>])
----> <span class="synConstant">3</span> df.at[<span class="synConstant">0</span>, <span class="synConstant">'col_A'</span>] = my_list
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/pandas/core/indexing.py <span class="synStatement">in</span> __setitem__(self, key, value)
<span class="synConstant">2089</span> <span class="synStatement">return</span>
<span class="synConstant">2090</span>
-> <span class="synConstant">2091</span> <span class="synStatement">return</span> <span class="synIdentifier">super</span>().__setitem__(key, value)
<span class="synConstant">2092</span>
<span class="synConstant">2093</span>
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/pandas/core/indexing.py <span class="synStatement">in</span> __setitem__(self, key, value)
<span class="synConstant">2040</span> <span class="synStatement">raise</span> <span class="synType">ValueError</span>(<span class="synConstant">"Not enough indexers for scalar access (setting)!"</span>)
<span class="synConstant">2041</span>
-> <span class="synConstant">2042</span> self.obj._set_value(*key, value=value, takeable=self._takeable)
<span class="synConstant">2043</span>
<span class="synConstant">2044</span>
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/pandas/core/frame.py <span class="synStatement">in</span> _set_value(self, index, col, value, takeable)
<span class="synConstant">3145</span> validate_numeric_casting(series.dtype, value)
<span class="synConstant">3146</span>
-> <span class="synConstant">3147</span> series._values[loc] = value
<span class="synConstant">3148</span> <span class="synComment"># Note: trying to use series._set_value breaks tests in</span>
<span class="synConstant">3149</span> <span class="synComment"># tests.frame.indexing.test_indexing and tests.indexing.test_partial</span>
<span class="synType">ValueError</span>: setting an array element <span class="synStatement">with</span> a sequence.
</pre>
<p>これはデータ型(dtype)の問題である。<br />
<code>col_A</code>の列は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%E2%C6%B0%BE%AE%BF%F4%C5%C0%BF%F4">浮動小数点数</a>を1つ入れるデータ型になっているので、配列を代入しようとするとデータ型が合わずにエラーになるのだ。</p>
<p>pandasのdtypeについては、こちらも参照。公式ドキュメントを個人的に翻訳した記事だ。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2F2019%2F11%2F23%2F162709" title="pandasのデータ型、dtypeについて 公式ドキュメントを翻訳した - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/2019/11/23/162709">linus-mk.hatenablog.com</a></cite></p>
<pre class="code lang-python" data-lang="python" data-unlink>df.dtypes
<span class="synComment"># --------------------</span>
col_A float64
col_B float64
col_string <span class="synIdentifier">object</span>
dtype: <span class="synIdentifier">object</span>
</pre>
<p>listを入れるならば、該当する列のデータ型をobjectにすれば良い。それにはastype()関数を用いる。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df[<span class="synConstant">'col_A'</span>] = df[<span class="synConstant">'col_A'</span>].astype(<span class="synConstant">'object'</span>)
df.dtypes
<span class="synComment"># --------------------</span>
col_A <span class="synIdentifier">object</span>
col_B float64
col_string <span class="synIdentifier">object</span>
dtype: <span class="synIdentifier">object</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">print</span>(df.at[<span class="synConstant">0</span>, <span class="synConstant">'col_A'</span>])
df.at[<span class="synConstant">0</span>, <span class="synConstant">'col_A'</span>] = my_list
<span class="synComment"># --------------------</span>
<span class="synConstant">1.2</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df
<span class="synComment"># --------------------</span>
col_A col_B col_string
<span class="synConstant">0</span> [<span class="synConstant">3</span>, <span class="synConstant">4</span>, <span class="synConstant">5</span>] <span class="synConstant">9.8</span> [another, <span class="synIdentifier">list</span>]
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7.6</span> good_morning
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5.4</span> [this, <span class="synStatement">is</span>, a, <span class="synIdentifier">list</span>]
</pre>
<h2 id="参考文献">参考文献</h2>
<p><a href="https://stackoverflow.com/questions/26483254/python-pandas-insert-list-into-a-cell">Python pandas insert list into a cell - Stack Overflow</a><br />
<a href="https://stackoverflow.com/questions/38133961/pandas-how-to-store-a-list-in-a-dataframe">python - pandas: how to store a list in a dataframe? - Stack Overflow</a></p>
<p>それでは。</p>
soratokimitonoaidani
pandasでValueError: len(left_on) must equal the number of levels in the index of "right"
hatenablog://entry/26006613628351267
2020-09-15T21:15:50+09:00
2021-03-10T23:32:22+09:00 pandasを使ってDataFrameを結合しようとしたら、ValueError: len(left_on) must equal the number of levels in the index of "right" という見慣れないエラーが出てきた。 mergeを使うべきところでjoinを使ったのが原因だった。 以下のStackOverflowを見たら疑問は解決したけど、自分の頭を整理するためにまとめておく。 python - Why does Pandas inner join give ValueError: len(left_on) must equal the number of…
<p>pandasを使ってDataFrameを結合しようとしたら、<code>ValueError: len(left_on) must equal the number of levels in the index of "right"</code><br />
という見慣れないエラーが出てきた。</p>
<p>mergeを使うべきところでjoinを使ったのが原因だった。<br />
以下のStackOverflowを見たら疑問は解決したけど、自分の頭を整理するためにまとめておく。<br />
<a href="https://stackoverflow.com/questions/28228781/why-does-pandas-inner-join-give-valueerror-lenleft-on-must-equal-the-number-o">python - Why does Pandas inner join give ValueError: len(left_on) must equal the number of levels in the index of "right"? - Stack Overflow</a></p>
<p>また、joinの<code>on</code>キーワードがどのように使われているのかについても調べたので、併せてまとめる。</p>
<ul class="table-of-contents">
<li><a href="#mergeを使うべきところでjoinを使ったのが原因だった">mergeを使うべきところでjoinを使ったのが原因だった</a></li>
<li><a href="#DataFrameを結合する関数mergeとjoinの違い">DataFrameを結合する関数、mergeとjoinの違い。</a></li>
<li><a href="#joinにはleft_on-right_onがない">joinにはleft_on, right_onがない</a></li>
<li><a href="#joinでonを1列だけ指定した場合のエラー">joinでonを1列だけ指定した場合のエラー</a></li>
<li><a href="#joinのonキーワードは一体何をしているのか">joinのonキーワードは一体何をしているのか?</a></li>
<li><a href="#エラーの意味を解明する">エラーの意味を解明する</a></li>
<li><a href="#参考文献">参考文献</a></li>
</ul>
<h2 id="mergeを使うべきところでjoinを使ったのが原因だった">mergeを使うべきところでjoinを使ったのが原因だった</h2>
<ul>
<li>DataFrameを結合するためにmergeを使うべきところで、joinを使う</li>
<li>onに複数列を指定する</li>
</ul>
<p>以上の条件で発生するエラーであった。</p>
<p>pandasのコミッターであるsinhrksさんの記事がとても秀逸なので、DataFrameを連結・結合する処理で困ったらここを見よう。<br />
<a href="http://sinhrks.hatenablog.com/entry/2015/01/28/073327">Python pandas 図でみる データ連結 / 結合処理 - StatsFragments</a><br />
その後、公式ドキュメントにもこの記事が追加された。上記は2015年の記事なので、最新の仕様については公式ドキュメントを見たほうが良い。<br />
本記事の例は公式ドキュメントのものを一部変更している。<br />
<a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html">Merge, join, concatenate and compare — pandas 1.2.3 documentation</a></p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd
<span class="synPreProc">import</span> numpy <span class="synStatement">as</span> np
pd.options.display.notebook_repr_html = <span class="synIdentifier">False</span> <span class="synComment"># jupyter notebook上での出力形式を制御するために書いています。無くても動きます。</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 動作環境の確認</span>
<span class="synIdentifier">print</span>(pd.__version__)
<span class="synIdentifier">print</span>(np.__version__)
<span class="synComment"># --------------------</span>
<span class="synConstant">1.1</span>.<span class="synConstant">2</span>
<span class="synConstant">1.19</span>.<span class="synConstant">1</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df_left = pd.DataFrame({<span class="synConstant">'key1'</span>: [<span class="synConstant">'K0'</span>, <span class="synConstant">'K0'</span>, <span class="synConstant">'K1'</span>, <span class="synConstant">'K2'</span>],
<span class="synConstant">'key2'</span>: [<span class="synConstant">'K0'</span>, <span class="synConstant">'K1'</span>, <span class="synConstant">'K0'</span>, <span class="synConstant">'K1'</span>],
<span class="synConstant">'A'</span>: [<span class="synConstant">'A0'</span>, <span class="synConstant">'A1'</span>, <span class="synConstant">'A2'</span>, <span class="synConstant">'A3'</span>],
<span class="synConstant">'B'</span>: [<span class="synConstant">'B0'</span>, <span class="synConstant">'B1'</span>, <span class="synConstant">'B2'</span>, <span class="synConstant">'B3'</span>]})
df_right = pd.DataFrame({<span class="synConstant">'key1'</span>: [<span class="synConstant">'K0'</span>, <span class="synConstant">'K1'</span>, <span class="synConstant">'K1'</span>, <span class="synConstant">'K2'</span>],
<span class="synConstant">'key2'</span>: [<span class="synConstant">'K0'</span>, <span class="synConstant">'K0'</span>, <span class="synConstant">'K0'</span>, <span class="synConstant">'K0'</span>],
<span class="synConstant">'C'</span>: [<span class="synConstant">'C0'</span>, <span class="synConstant">'C1'</span>, <span class="synConstant">'C2'</span>, <span class="synConstant">'C3'</span>],
<span class="synConstant">'D'</span>: [<span class="synConstant">'D0'</span>, <span class="synConstant">'D1'</span>, <span class="synConstant">'D2'</span>, <span class="synConstant">'D3'</span>]})
<span class="synIdentifier">print</span>(df_left)
<span class="synIdentifier">print</span>(<span class="synConstant">"~~~~~~"</span>)
<span class="synIdentifier">print</span>(df_right)
<span class="synComment"># --------------------</span>
key1 key2 A B
<span class="synConstant">0</span> K0 K0 A0 B0
<span class="synConstant">1</span> K0 K1 A1 B1
<span class="synConstant">2</span> K1 K0 A2 B2
<span class="synConstant">3</span> K2 K1 A3 B3
~~~~~~
key1 key2 C D
<span class="synConstant">0</span> K0 K0 C0 D0
<span class="synConstant">1</span> K1 K0 C1 D1
<span class="synConstant">2</span> K1 K0 C2 D2
<span class="synConstant">3</span> K2 K0 C3 D3
</pre>
<p>この2つのDataFrameを['key1', 'key2']という2つの列を基準に結合する。これはmergeを使うのが正しいやり方だ。</p>
<pre class="code lang-python" data-lang="python" data-unlink>result = pd.merge(df_left,df_right, on=[<span class="synConstant">'key1'</span>, <span class="synConstant">'key2'</span>])
result
<span class="synComment"># --------------------</span>
key1 key2 A B C D
<span class="synConstant">0</span> K0 K0 A0 B0 C0 D0
<span class="synConstant">1</span> K1 K0 A2 B2 C1 D1
<span class="synConstant">2</span> K1 K0 A2 B2 C2 D2
</pre>
<p>さらに、DataFrameに対してmerge関数を適用することもできる。結果は全く同じになる。</p>
<pre class="code lang-python" data-lang="python" data-unlink>result = df_left.merge(df_right, on=[<span class="synConstant">'key1'</span>, <span class="synConstant">'key2'</span>])
result
<span class="synComment"># --------------------</span>
key1 key2 A B C D
<span class="synConstant">0</span> K0 K0 A0 B0 C0 D0
<span class="synConstant">1</span> K1 K0 A2 B2 C1 D1
<span class="synConstant">2</span> K1 K0 A2 B2 C2 D2
</pre>
<p>上記において、間違えてmergeではなくjoinを使ってしまった。</p>
<pre class="code lang-python" data-lang="python" data-unlink>result = df_left.join(df_right, on=[<span class="synConstant">'key1'</span>, <span class="synConstant">'key2'</span>])
<span class="synComment"># --------------------</span>
---------------------------------------------------------------------------
<span class="synType">ValueError</span> Traceback (most recent call last)
<ipython-<span class="synIdentifier">input</span>-<span class="synConstant">23</span>-302ff90d7a3b> <span class="synStatement">in</span> <module>
----> <span class="synConstant">1</span> result = df_left.join(df_right, on=[<span class="synConstant">'key1'</span>, <span class="synConstant">'key2'</span>])
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/pandas/core/frame.py <span class="synStatement">in</span> join(self, other, on, how, lsuffix, rsuffix, sort)
<span class="synConstant">7867</span> <span class="synConstant">5</span> K5 A5 NaN
<span class="synConstant">7868</span> <span class="synConstant">"""</span>
<span class="synConstant"> -> 7869 return self._join_compat(</span>
<span class="synConstant"> 7870 other, on=on, how=how, lsuffix=lsuffix, rsuffix=rsuffix, sort=sort</span>
<span class="synConstant"> 7871 )</span>
<span class="synConstant"> /usr/local/lib/python3.8/site-packages/pandas/core/frame.py in _join_compat(self, other, on, how, lsuffix, rsuffix, sort)</span>
<span class="synConstant"> 7883 </span>
<span class="synConstant"> 7884 if isinstance(other, DataFrame):</span>
<span class="synConstant"> -> 7885 return merge(</span>
<span class="synConstant"> 7886 self,</span>
<span class="synConstant"> 7887 other,</span>
<span class="synConstant"> /usr/local/lib/python3.8/site-packages/pandas/core/reshape/merge.py in merge(left, right, how, on, left_on, right_on, left_index, right_index, sort, suffixes, copy, indicator, validate)</span>
<span class="synConstant"> 72 validate=None,</span>
<span class="synConstant"> 73 ) -> "DataFrame":</span>
<span class="synConstant"> ---> 74 op = _MergeOperation(</span>
<span class="synConstant"> 75 left,</span>
<span class="synConstant"> 76 right,</span>
<span class="synConstant"> /usr/local/lib/python3.8/site-packages/pandas/core/reshape/merge.py in __init__(self, left, right, how, on, left_on, right_on, axis, left_index, right_index, sort, suffixes, copy, indicator, validate)</span>
<span class="synConstant"> 643 warnings.warn(msg, UserWarning)</span>
<span class="synConstant"> 644 </span>
<span class="synConstant"> --> 645 self._validate_specification()</span>
<span class="synConstant"> 646 </span>
<span class="synConstant"> 647 # note this function has side effects</span>
<span class="synConstant"> /usr/local/lib/python3.8/site-packages/pandas/core/reshape/merge.py in _validate_specification(self)</span>
<span class="synConstant"> 1233 if self.right_index:</span>
<span class="synConstant"> 1234 if len(self.left_on) != self.right.index.nlevels:</span>
<span class="synConstant"> -> 1235 raise ValueError(</span>
<span class="synConstant"> 1236 "len(left_on) must equal the number "</span>
<span class="synConstant"> 1237 'of levels in the index of "right"'</span>
<span class="synConstant"> ValueError: len(left_on) must equal the number of levels in the index of "right"</span>
</pre>
<p>はい。ValueError: len(left_on) must equal the number of levels in the index of "right" というエラーが発生した。</p>
<p>一応注記しておくと、エラー文の中の"right"はDataFrameの変数名とは無関係である。<br />
join中で右側に指定したDataFrame、という意味であろう。</p>
<p>上記のコードを正しく動かすためには、「joinではなくmergeを使えば良い」で終わりである。<br />
が、どうしてこんなエラーになったのか、いまいちよく分からん。<br />
では、他の場合でもmergeではなくjoinにしてしまったら、どういうエラーが出るのだろうか?試してみよう。</p>
<h2 id="DataFrameを結合する関数mergeとjoinの違い">DataFrameを結合する関数、mergeとjoinの違い。</h2>
<p>その前に一旦、mergeとjoinの違いを見ておこう。</p>
<p><a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html">Merge, join, concatenate and compare — pandas 1.2.3 documentation</a></p>
<blockquote><p>DataFrame.join() is a convenient method for combining the columns of two potentially differently-indexed DataFrames into a single result DataFrame.<br />
拙訳:DataFrame.join()は、異なるindexの可能性のある2つの列を結合し、1つのDataFrameを結果として出力する、便利なメソッドである。</p></blockquote>
<p>joinはあくまで便利メソッドなんだよね。<br />
mergeは列やindexを使ってDataFrameを結合できる。joinはindexを使ってDataFrameを結合できる。<br />
mergeはjoinを含んでjoinより広い範囲のことができるので、joinを使うところはmergeで置き換えることもできる。</p>
<p>なお、pandasのドキュメントから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>に飛んで、<br />
<a href="https://github.com/pandas-dev/pandas/blob/v1.1.2/pandas/core/frame.py#L7749-L7871">pandas/frame.py at v1.1.2 · pandas-dev/pandas · GitHub</a><br />
を見ると、joinはその内部でmerge関数を実行しているのが分かる。</p>
<h2 id="joinにはleft_on-right_onがない">joinにはleft_on, right_onがない</h2>
<p>mergeにはleft_on, right_onというパラメータが指定できるが、joinにはこれらのパラメータがない。
したがって、joinでleft_on, right_onを指定すると「そんなパラメータは指定できません」というエラーを返す。これは分かりやすいね。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.merge.html</span>
df1 = pd.DataFrame({<span class="synConstant">'lkey'</span>: [<span class="synConstant">'foo'</span>, <span class="synConstant">'bar'</span>, <span class="synConstant">'baz'</span>, <span class="synConstant">'foo'</span>],
<span class="synConstant">'value'</span>: [<span class="synConstant">1</span>, <span class="synConstant">2</span>, <span class="synConstant">3</span>, <span class="synConstant">5</span>]})
df2 = pd.DataFrame({<span class="synConstant">'rkey'</span>: [<span class="synConstant">'foo'</span>, <span class="synConstant">'bar'</span>, <span class="synConstant">'baz'</span>, <span class="synConstant">'foo'</span>],
<span class="synConstant">'value'</span>: [<span class="synConstant">5</span>, <span class="synConstant">6</span>, <span class="synConstant">7</span>, <span class="synConstant">8</span>]})
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df1
<span class="synComment"># --------------------</span>
lkey value
<span class="synConstant">0</span> foo <span class="synConstant">1</span>
<span class="synConstant">1</span> bar <span class="synConstant">2</span>
<span class="synConstant">2</span> baz <span class="synConstant">3</span>
<span class="synConstant">3</span> foo <span class="synConstant">5</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df2
<span class="synComment"># --------------------</span>
rkey value
<span class="synConstant">0</span> foo <span class="synConstant">5</span>
<span class="synConstant">1</span> bar <span class="synConstant">6</span>
<span class="synConstant">2</span> baz <span class="synConstant">7</span>
<span class="synConstant">3</span> foo <span class="synConstant">8</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df1.merge(df2, left_on=<span class="synConstant">'lkey'</span>, right_on=<span class="synConstant">'rkey'</span>)
<span class="synComment"># --------------------</span>
lkey value_x rkey value_y
<span class="synConstant">0</span> foo <span class="synConstant">1</span> foo <span class="synConstant">5</span>
<span class="synConstant">1</span> foo <span class="synConstant">1</span> foo <span class="synConstant">8</span>
<span class="synConstant">2</span> foo <span class="synConstant">5</span> foo <span class="synConstant">5</span>
<span class="synConstant">3</span> foo <span class="synConstant">5</span> foo <span class="synConstant">8</span>
<span class="synConstant">4</span> bar <span class="synConstant">2</span> bar <span class="synConstant">6</span>
<span class="synConstant">5</span> baz <span class="synConstant">3</span> baz <span class="synConstant">7</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df1.join(df2, left_on=<span class="synConstant">'lkey'</span>, right_on=<span class="synConstant">'rkey'</span>)
<span class="synComment"># --------------------</span>
---------------------------------------------------------------------------
<span class="synType">TypeError</span> Traceback (most recent call last)
<ipython-<span class="synIdentifier">input</span>-<span class="synConstant">7</span>-b2a9def786b8> <span class="synStatement">in</span> <module>
----> <span class="synConstant">1</span> df1.join(df2, left_on=<span class="synConstant">'lkey'</span>, right_on=<span class="synConstant">'rkey'</span>)
<span class="synType">TypeError</span>: join() got an unexpected keyword argument <span class="synConstant">'left_on'</span>
</pre>
<h2 id="joinでonを1列だけ指定した場合のエラー">joinでonを1列だけ指定した場合のエラー</h2>
<p>onを複数列指定したときは最初に書いたエラーになる。1列だけの場合はどうなるだろうか?</p>
<pre class="code lang-python" data-lang="python" data-unlink>df1 = pd.DataFrame({<span class="synConstant">'key'</span>: [<span class="synConstant">'foo'</span>, <span class="synConstant">'bar'</span>, <span class="synConstant">'baz'</span>, <span class="synConstant">'foo'</span>],
<span class="synConstant">'value_df1'</span>: [<span class="synConstant">1</span>, <span class="synConstant">2</span>, <span class="synConstant">3</span>, <span class="synConstant">5</span>]})
df2 = pd.DataFrame({<span class="synConstant">'key'</span>: [<span class="synConstant">'foo'</span>, <span class="synConstant">'bar'</span>, <span class="synConstant">'baz'</span>, <span class="synConstant">'foo'</span>],
<span class="synConstant">'value_df2'</span>: [<span class="synConstant">5</span>, <span class="synConstant">6</span>, <span class="synConstant">7</span>, <span class="synConstant">8</span>]})
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df1.merge(df2, on=<span class="synConstant">'key'</span>)
<span class="synComment"># --------------------</span>
key value_df1 value_df2
<span class="synConstant">0</span> foo <span class="synConstant">1</span> <span class="synConstant">5</span>
<span class="synConstant">1</span> foo <span class="synConstant">1</span> <span class="synConstant">8</span>
<span class="synConstant">2</span> foo <span class="synConstant">5</span> <span class="synConstant">5</span>
<span class="synConstant">3</span> foo <span class="synConstant">5</span> <span class="synConstant">8</span>
<span class="synConstant">4</span> bar <span class="synConstant">2</span> <span class="synConstant">6</span>
<span class="synConstant">5</span> baz <span class="synConstant">3</span> <span class="synConstant">7</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df1.join(df2, on=<span class="synConstant">'key'</span>)
<span class="synComment"># --------------------</span>
---------------------------------------------------------------------------
<span class="synType">ValueError</span> Traceback (most recent call last)
<ipython-<span class="synIdentifier">input</span>-<span class="synConstant">10</span>-3d5d0d53e524> <span class="synStatement">in</span> <module>
----> <span class="synConstant">1</span> df1.join(df2, on=<span class="synConstant">'key'</span>)
/usr/local/lib/python3.<span class="synConstant">8</span>/site-packages/pandas/core/frame.py <span class="synStatement">in</span> join(self, other, on, how, lsuffix, rsuffix, sort)
<span class="synConstant">7867</span> <span class="synConstant">5</span> K5 A5 NaN
<span class="synConstant">7868</span> <span class="synConstant">"""</span>
<span class="synConstant"> -> 7869 return self._join_compat(</span>
<span class="synConstant"> 7870 other, on=on, how=how, lsuffix=lsuffix, rsuffix=rsuffix, sort=sort</span>
<span class="synConstant"> 7871 )</span>
<span class="synConstant"> /usr/local/lib/python3.8/site-packages/pandas/core/frame.py in _join_compat(self, other, on, how, lsuffix, rsuffix, sort)</span>
<span class="synConstant"> 7883 </span>
<span class="synConstant"> 7884 if isinstance(other, DataFrame):</span>
<span class="synConstant"> -> 7885 return merge(</span>
<span class="synConstant"> 7886 self,</span>
<span class="synConstant"> 7887 other,</span>
<span class="synConstant"> /usr/local/lib/python3.8/site-packages/pandas/core/reshape/merge.py in merge(left, right, how, on, left_on, right_on, left_index, right_index, sort, suffixes, copy, indicator, validate)</span>
<span class="synConstant"> 72 validate=None,</span>
<span class="synConstant"> 73 ) -> "DataFrame":</span>
<span class="synConstant"> ---> 74 op = _MergeOperation(</span>
<span class="synConstant"> 75 left,</span>
<span class="synConstant"> 76 right,</span>
<span class="synConstant"> /usr/local/lib/python3.8/site-packages/pandas/core/reshape/merge.py in __init__(self, left, right, how, on, left_on, right_on, axis, left_index, right_index, sort, suffixes, copy, indicator, validate)</span>
<span class="synConstant"> 654 # validate the merge keys dtypes. We may need to coerce</span>
<span class="synConstant"> 655 # to avoid incompatible dtypes</span>
<span class="synConstant"> --> 656 self._maybe_coerce_merge_keys()</span>
<span class="synConstant"> 657 </span>
<span class="synConstant"> 658 # If argument passed to validate,</span>
<span class="synConstant"> /usr/local/lib/python3.8/site-packages/pandas/core/reshape/merge.py in _maybe_coerce_merge_keys(self)</span>
<span class="synConstant"> 1163 inferred_right in string_types and inferred_left not in string_types</span>
<span class="synConstant"> 1164 ):</span>
<span class="synConstant"> -> 1165 raise ValueError(msg)</span>
<span class="synConstant"> 1166 </span>
<span class="synConstant"> 1167 # datetimelikes must match exactly</span>
<span class="synConstant"> ValueError: You are trying to merge on object and int64 columns. If you wish to proceed you should use pd.concat</span>
</pre>
<p>んーー?
ちょっと言ってることがよく分からない。<br />
mergeを使うべきところでうっかりjoinを使ってしまったので「<code>you should use pd.merge</code>」って言ってくれるのが一番ありがたい。しかし、「<code>you should use pd.concat</code>」と言われてしまった。一体何で……?</p>
<h2 id="joinのonキーワードは一体何をしているのか">joinのonキーワードは一体何をしているのか?</h2>
<p>join関数は何に基づいてDataFrameを結合するのか?<br />
それはindexである。joinを使った時点で、indexに基づいて結合すると決まっている。<br />
じゃあわざわざonで指定する必要も無いのではないか?</p>
<p>joinのonキーワードについてドキュメントを見てみよう。</p>
<p>以下2つの操作は完全に等価である、とドキュメントには書いてある(<a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html#joining-key-columns-on-an-index">Merge, join, concatenate and compare — pandas 1.2.3 documentation</a>)。</p>
<blockquote><p><code>left.join(right, on=key_or_keys)</code><br />
<code>pd.merge(left, right, left_on=key_or_keys, right_index=True, how='left', sort=False)</code></p></blockquote>
<p>公式ドキュメントを色々読むと、どうやら以下の仕様であると分かった。</p>
<ul>
<li>joinはDataFrame.join()の形式で使う。pd.joinの形式では使えない。</li>
<li>joinの中で<code>on</code>を指定した場合、joinの左側のDataFrameで使う列名(またはindexレベル名)となる。</li>
<li>joinの中で<code>on</code>を指定した場合でも、joinの右側のDataFrameでindexを基準に結合するということは変わらない。(常に<code>right_index=True</code>になることに注意!)</li>
<li>joinの中で<code>on</code>に複数の値を指定した場合、右側のDataFrameはMultiIndexでなければならない。</li>
<li><a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html#joining-key-columns-on-an-index">Merge, join, concatenate and compare — pandas 1.2.3 documentation</a>には、joinの中で<code>on</code>に単一の値、複数の値を指定した例がある。</li>
</ul>
<h2 id="エラーの意味を解明する">エラーの意味を解明する</h2>
<p>joinの<code>on</code>の意味を把握すると、ようやく最初に書いた謎めいたエラーの意味がわかってくる。最初の例からコードとエラー文を再掲する。</p>
<pre class="code lang-python" data-lang="python" data-unlink>result = df_left.join(df_right, on=[<span class="synConstant">'key1'</span>, <span class="synConstant">'key2'</span>])
<span class="synComment"># --------------------</span>
<span class="synType">ValueError</span>: <span class="synIdentifier">len</span>(left_on) must equal the number of levels <span class="synStatement">in</span> the index of <span class="synConstant">"right"</span>
</pre>
<p>pandasの気持ちになると、こういう思考過程でエラーを上げている。<br />
「joinに2つの要素からなる<code>on</code>が指定されているから、右側のDataFrameは2段階のindexからなるMultiIndexのDataFrameのはずだよね。あれ、それなのに実際には右側のDataFrameはMultiIndexではないぞ。これはおかしいぞ、エラーだ。<strong>onの中の要<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%BF%F4">素数</a>(len(left_on)) ≠ 右側のindexの段階数'(the number of levels in the index of "right")</strong>なので、エラーを出そう。」<br />
内部のコードを見てはいないが、エラー文章とも整合するので、多分こうだろう。</p>
<p>次のエラー。コードとエラー文を再掲する。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df1.join(df2, on=<span class="synConstant">'key'</span>)
<span class="synComment"># --------------------</span>
<span class="synType">ValueError</span>: You are trying to merge on <span class="synIdentifier">object</span> <span class="synStatement">and</span> int64 columns. If you wish to proceed you should use pd.concat
</pre>
<p>pandasの気持ちになると、こういう思考過程でエラーを上げている。<br />
「joinに1つの要素からなる<code>on</code>が指定されている。左側のDataFrameのkey列と、右側のDataFrameのindexに基づいてデータを結合しよう。あれ、<strong>左側のDataFrameのkey列はobject型(文字列が入っている)、右側のDataFrameのindexはint64型</strong>じゃないか。これじゃデータを結合できるわけが無いや。エラーを出そう。」<br />
内部のコードをあまり見ていないが、エラー文章とも整合するので、多分こうだろう。</p>
<p>(付け加えると、pandas内部の_maybe_coerce_merge_keys()関数で、違うdtypeでもうまく変換してdtypeを揃えられないか試しているようだ。そのおかげで、例えばint64の列とint8の列はうまくmergeできる。だが、文字列とint64ではdtypeを揃えるのはどうやっても無理なので、結局エラーになる。)</p>
<h2 id="参考文献">参考文献</h2>
<p>今回参考にしたページ。どれもここまでに既に挙げたものだ。</p>
<p>エラーメッセージで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B0%A5%B0%A4%EB">ググる</a>と真っ先に出てくるStackOverflow。<br />
<a href="https://stackoverflow.com/questions/28228781/why-does-pandas-inner-join-give-valueerror-lenleft-on-must-equal-the-number-o">python - Why does Pandas inner join give ValueError: len(left_on) must equal the number of levels in the index of "right"? - Stack Overflow</a></p>
<p>DataFrameの結合について。
<a href="http://sinhrks.hatenablog.com/entry/2015/01/28/073327">Python pandas 図でみる データ連結 / 結合処理 - StatsFragments</a>
その後、この記事を元に公式ドキュメントにも英語の記事が追加された。
<a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html">Merge, join, concatenate and compare — pandas 1.2.3 documentation</a></p>
<p>今回公式ドキュメントを少し詳しく読んでみたが、説明の充実度は公式ドキュメントのほうが圧倒的に高い。
もとはこのブログ記事であるとはいえ、英語に翻訳したあとに大幅な加筆修正が入っている。<br />
その分、どこに何が書いてあるかがすぐには分かりづらい面もある。</p>
<p>初心者は日本語の<a href="http://sinhrks.hatenablog.com/entry/2015/01/28/073327">Python pandas 図でみる データ連結 / 結合処理 - StatsFragments</a><br />
少し慣れてきて詳しいことを知りたかったら、内容たっぷりの公式ドキュメントの<a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html">Merge, join, concatenate and compare — pandas 1.2.3 documentation</a><br />
が良いと思った。</p>
<p>今回調べてみて、Rや<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>でいくらjoinが使われていても、pandasではmergeを使うんだと覚えておこう、と思った。</p>
<p>それでは。</p>
soratokimitonoaidani
「今回は、ファイルをダウンロードできませんでした」iPad ProでPDFのダウンロード失敗
hatenablog://entry/26006613620654540
2020-08-27T23:19:26+09:00
2020-08-27T23:21:12+09:00 iPad Proで「今回は、ファイルをダウンロードできませんでした」とメッセージが出て、ダウンロードに失敗するという現象が起きて困った。 検索しても同じ症状になったという人が出てこない。 誰かの役に立つかもしれないので、一応メモしておく。 環境 iPad Pro (11 inch, 2018年11月に発売された版) ネットワーク:自宅のWi-Fiに接続 ブラウザ:Google Chrome 発生事象 ECサイトで電子書籍を買った(InformITで「Effective Python」の電子書籍を買った)。PDFのデータをダウンロードしてiPad上で読もうと思い、ChromeからGoodNote…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iPad">iPad</a> Proで「今回は、ファイルをダウンロードできませんでした」とメッセージが出て、ダウンロードに失敗するという現象が起きて困った。<br />
検索しても同じ症状になったという人が出てこない。<br />
誰かの役に立つかもしれないので、一応メモしておく。</p>
<h2>環境</h2>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iPad">iPad</a> Pro (11 inch, 2018年11月に発売された版)</li>
<li>ネットワーク:自宅の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Wi-Fi">Wi-Fi</a>に接続</li>
<li>ブラウザ:<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Chrome">Google Chrome</a></li>
</ul>
<h2>発生事象</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/EC%A5%B5%A5%A4%A5%C8">ECサイト</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%C5%BB%D2%BD%F1%C0%D2">電子書籍</a>を買った(InformITで「Effective <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>」の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%C5%BB%D2%BD%F1%C0%D2">電子書籍</a>を買った)。PDFのデータをダウンロードして<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPad">iPad</a>上で読もうと思い、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>からGoodNotesにデータを送ろうとした。「<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPad">iPad</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>からpdfをGoodnotesに送る方法」は、この記事にまとめてある。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2F2019%2F12%2F07%2F233001" title="iPadでChromeからpdfをGoodnotesに送る方法 - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/2019/12/07/233001">linus-mk.hatenablog.com</a></cite></p>
<p>上記に書いた通りの手順で、中央ページを一度タップして、
右下に出現した「次で開く…」をタップすると、「今回は、ファイルをダウンロードできませんでした」という見たことのないメッセージが出てきた。</p>
<p>何度か同じ操作をしてみても、同じエラーメッセージが出てきてダウンロードに失敗する。</p>
<p>右上のメニューから「再読み込み」をして更新→変わらない。</p>
<p>全てのPDFファイルで同じ状況なのか?別のPDFファイルはどうか?<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/chrome">chrome</a>で「pdf」で検索して最初に出てきたPDFファイルに対して同様の操作をする→通常通りGoodNotesにコピーできた。 <br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/arXiv">arXiv</a>から適当に選んだPDFファイルでも、通常通りGoodNotesにコピーできた。 <br />
全てのPDFではなく、このPDFに特有の問題のようだ?</p>
<h2>解決法</h2>
<p>キャッシュをクリアしたらうまく行った。 </p>
<p>右上のメニューから「履歴」→「閲覧履歴データを削除…」→「キャッシュされた画像とファイル」を選択→「閲覧履歴データの削除」を実行<br />
→ダウンロードに成功した。</p>
<p>一体、何だったんだろう?</p>
<p>それでは。</p>
soratokimitonoaidani
effective python 第2版の翻訳改善点 1〜3章
hatenablog://entry/26006613618231672
2020-08-22T18:46:36+09:00
2022-08-28T21:57:03+09:00 オライリー・ジャパンから発売された「Effective Python 第2版 Pythonプログラムを改良する90項目」の日本語訳の改善提案である。気になった箇所について、原文と照らし合わせて問題点を述べ、日本語訳を自分で書き直している。 注意事項 無償の翻訳と出版された翻訳の違い 第1章 p.20 p.25 項目6 p.33 項目9 p.36 項目10 第2章 p.46 項目12 p.47 項目13 p.56 項目15 p.57 項目15 p.66 項目16 第3章 p.88 項目23 p.89 項目23 p.95 項目25 注意事項 いやー、もう、この記事を書くのが怖いといえばだいぶ怖い。…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%E9%A5%A4%A5%EA%A1%BC%A1%A6%A5%B8%A5%E3%A5%D1%A5%F3">オライリー・ジャパン</a>から発売された「Effective <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 第2版 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>プログラムを改良する90項目」の日本語訳の改善提案である。気になった箇所について、原文と照らし合わせて問題点を述べ、日本語訳を自分で書き直している。</p>
<p><a href="https://www.amazon.co.jp/Effective-Python-%E2%80%95Python%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E6%94%B9%E8%89%AF%E3%81%99%E3%82%8B90%E9%A0%85%E7%9B%AE-Brett-Slatkin/dp/4873119170/ref=as_li_ss_il?ie=UTF8&linkCode=li3&tag=limk-22&linkId=2a51865e1c1f7f08ba09a29035553721&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4873119170&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=limk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=limk-22&language=ja_JP&l=li3&o=9&a=4873119170" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
<a href="https://www.amazon.co.jp/Effective-Python-Specific-Software-Development/dp/0134853989/ref=as_li_ss_il?_encoding=UTF8&pd_rd_i=0134853989&pd_rd_r=d28c24ba-e01f-4735-af95-e659822ba92e&pd_rd_w=4SXlO&pd_rd_wg=rFVp3&pf_rd_p=4b55d259-ebf0-4306-905a-7762d1b93740&pf_rd_r=DNPBCCHKFVCMJNWN4N36&psc=1&refRID=DNPBCCHKFVCMJNWN4N36&linkCode=li3&tag=limk-22&linkId=454c72d4808babf409499868fb8d156a&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=0134853989&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=limk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=limk-22&language=ja_JP&l=li3&o=9&a=0134853989" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
<ul class="table-of-contents">
<li><a href="#注意事項">注意事項</a></li>
<li><a href="#無償の翻訳と出版された翻訳の違い">無償の翻訳と出版された翻訳の違い</a></li>
<li><a href="#第1章">第1章</a><ul>
<li><a href="#p20">p.20</a></li>
<li><a href="#p25-項目6">p.25 項目6</a></li>
<li><a href="#p33-項目9">p.33 項目9</a></li>
<li><a href="#p36-項目10">p.36 項目10</a></li>
</ul>
</li>
<li><a href="#第2章">第2章</a><ul>
<li><a href="#p46-項目12">p.46 項目12</a></li>
<li><a href="#p47-項目13">p.47 項目13</a></li>
<li><a href="#p56-項目15">p.56 項目15</a></li>
<li><a href="#p57-項目15">p.57 項目15</a></li>
<li><a href="#p66-項目16">p.66 項目16</a></li>
</ul>
</li>
<li><a href="#第3章">第3章</a><ul>
<li><a href="#p88-項目23">p.88 項目23</a></li>
<li><a href="#p89-項目23">p.89 項目23</a></li>
<li><a href="#p95-項目25">p.95 項目25</a></li>
</ul>
</li>
</ul>
<h2 id="注意事項">注意事項</h2>
<p>いやー、もう、この記事を書くのが怖いといえばだいぶ怖い。
お前に訳文の誤りを指摘できるほどの<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>力があるか、英語力があるか、と問われたら、両方とも完璧には程遠い。記事の内容には正確を期しているが、それでも正確性は保証できない。</p>
<p>「Effective <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 第2版」の日本語版を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Amazon">Amazon</a>で、原著(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%C5%BB%D2%BD%F1%C0%D2">電子書籍</a>版)をInformIT(ピアソン社の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%C5%BB%D2%BD%F1%C0%D2">電子書籍</a>販売サイト)で購入した。<br />
以下でそれぞれの本の文章の一部を書いているが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C3%F8%BA%EE%B8%A2%CB%A1">著作権法</a>で定められた引用に該当する。
これは訳文の批評のために必要不可欠な引用である。</p>
<ul>
<li>選んだ箇所は私が問題だと思った部分である。文章の意味が間違っているところ(誤訳)と、文意が分かりづらいところとが混じっている。(両者をハッキリ判別するのは難しいので、どの部分がどちらかを示すことはしていない。)</li>
<li>ページ数は日本語版のページ数を示す。原著のページ数は省略した。</li>
<li>「日本語訳:」のあとに続く部分は「Effective <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 第2版」の日本語版からの引用である。</li>
<li>「原文:」のあとに続く部分は「Effective <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>: 90 Specific Ways to Write Better <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> (2nd Edition)」原著からの引用である。</li>
<li>また、「直訳」および「意訳」は原文から私がオリジナルで訳した文である。</li>
<li>「直訳」は英語の単語を極力そのまま日本語に置き換えたもの。
<ul>
<li>常に常体である。</li>
<li>「I / you」も訳出している。</li>
<li>高校の授業でやる英文和訳のような結果になるので、日本語として不自然な場合もある。</li>
</ul>
</li>
<li>「意訳」はそこから構文の変更などを加えて日本語として整えたものである。
<ul>
<li>常体か敬体かは元の日本語訳と同じとした。</li>
<li>「I / you」は日本語訳と同様、訳出しないことにした。</li>
<li>仮に私が翻訳するとしたら「意訳」の文章を最<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%AA%B7%EB">終結</a>果にするであろう。</li>
</ul>
</li>
</ul>
<h2 id="無償の翻訳と出版された翻訳の違い">無償の翻訳と出版された翻訳の違い</h2>
<p>「プログラミング関係の誤訳の指摘」というジャンルで、私がパッと思い出すのは</p>
<p><a href="https://takeda25.hatenablog.jp/entry/20151030/1446174043">腐った翻訳に対する態度について - アスペ日記</a><br />
<a href="https://takeda25.hatenablog.jp/entry/20141012/1413116292">善意のひどい訳について - アスペ日記</a><br />
<a href="https://takeda25.hatenablog.jp/entry/20141012/1413116149">「C言語でプログラミングする際の覚書」の誤訳箇所 - アスペ日記</a></p>
<p>である。でも上記で批判の対象となっているのは、趣味の、無償の翻訳である。<br />
今回私が論じるのは、すでに出版された本である。</p>
<p><strong>アマ翻訳とプロ翻訳の違いはなにか?</strong>
こっちのほうが指摘する側のハードルは高いんじゃないか。だって金をもらって翻訳している、プロの翻訳者が相手なんだから。<br />
ア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%C1%A5%E5%A5%A2">マチュア</a>の野球選手とプロの野球選手、どっちが投げる球が打てそうかと言われれば、どっちも無理だがプロの方がもっと無理だと思う(上手い喩えが思い付かない)。<br />
一方で、プロのほうが高い成果を出すことを期待されているのも確かだ。<br />
友人に髪を切ってもらって、変になったとしても、まぁ仕方ないか、と思えるけど、
美容室に行って変な髪型にされたら、おいおい、こっちは金払ってるのにこの結果は何やねん、と文句の一つも言いたくなるだろう(こっちも上手い喩えが思い付かない)。</p>
<p>ア<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%C1%A5%E5%A5%A2">マチュア</a>の翻訳かプロの翻訳かという問題とは別に、<strong>公式の翻訳か、非公式の翻訳か</strong>という面も同時にあるのではないか。
日本語版の最初には、以下のように書いてある。</p>
<blockquote><p>本書は、株式会社<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%E9%A5%A4%A5%EA%A1%BC%A1%A6%A5%B8%A5%E3%A5%D1%A5%F3">オライリー・ジャパン</a>がPearson Education, Inc. の許諾に基づき翻訳したものです。日本語版についての権利は、株式会社<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%E9%A5%A4%A5%EA%A1%BC%A1%A6%A5%B8%A5%E3%A5%D1%A5%F3">オライリー・ジャパン</a>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%DD%CD%AD">保有</a>します。</p></blockquote>
<p>言うまでもなく、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%E9%A5%A4%A5%EA%A1%BC">オライリー</a>から出ているこの本が公式な翻訳である。私がしようとしている翻訳は非公式であり趣味であり、おまけであり添え物である。</p>
<p>第1版の日本語版を本屋で何度か見たときも、見るたびに生硬な翻訳が目に付き、結局買うのを見送った。
第2版の原著が出版されるという話を聞いたときも(<a href="https://linus-mk.hatenablog.com/entry/2019/10/27/235143">Effective Python 第2版(原著)が出るみたいだよ - 子供の落書き帳 Renaissance</a>)、どうか別の翻訳者が訳してくれますようにと願った。しかし願いは虚しく、同じ翻訳者によって翻訳された日本語版が出版された。(普通に考えれば、第1版と同じ人が翻訳するのが合理的だろう。)
公式に本が出版された以上、この本の内容が、日本語訳のせいで分かりにくくなっている箇所があれば、その改善案を非公式に挙げて、本の価値をより高いものにするのが、私ができる最善の行動ではなかろうか。
私も全ては読めてはいないが、大変ためになる素晴らしい本である。これが翻訳のせいで価値が減じられるのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%D4%CB%DC%B0%D5">不本意</a>である。
したがって、Effecive <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>の出版に関わった人に喧嘩を売るつもりはなく、
<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>を使う人たちにも役立てれば良いと思う。
そういう意味だと「<a class="keyword" href="http://d.hatena.ne.jp/keyword/PRML">PRML</a>の副読本」の同人誌が、私のやろうしていることに近いかもしれない。(<a href="https://blog.cybozu.io/entry/654">風が吹けばジュンク堂で「機械学習の学習」 - Cybozu Inside Out | サイボウズエンジニアのブログ</a>)</p>
<p>また、上掲の誤訳の指摘では、必要以上に強い言葉を使っていたのでそれに対する非難も多かった。<br />
本記事は、翻訳の「批判・論評」であり、人の「誹謗中傷」とならないよう最大限留意したつもりだ。</p>
<h2 id="第1章">第1章</h2>
<h3 id="p20">p.20</h3>
<p>原文:The combination of expressiveness, terseness, and clarity provided by f-strings makes them the best built-in option for <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> programmers.<br />
日本語版:f文字列で与えられる表現性、簡潔性、明晰性の組み合わせは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>にとって組み込みの中の最良の選択です。</p>
<p>直訳:f文字列によってもたらされる表現力、簡潔性、明瞭性の組み合わせは、f文字列を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>にとって組み込みの中の最良の選択肢にしている。<br />
意訳:f文字列を使うと、コードを**に簡潔にそして明確に書けるので、f文字列は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>にとって組み込みの中の一番良い選択肢なのです。</p>
<p>何気なく読み飛ばしそうになったが、「表現性」とは一体何なんだろうか。私自身は「表現性がある/表現性が高い」のような言い方をした覚えがない。試しに引用符をつけてググってみると、「身体表現性障害」という病気のことばかりが出てくる。そこまで一般的な用語でないことだけは確かだ。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%D1%BC%AD%CF%BA">英辞郎</a>では「expressiveness」の訳語として「表現力」とだけ書いてある。
expressivenessのように派生語の場合は、その元の単語の意味を調べたほうが良い。
f-strings provide expressiveness, terseness, and clarityなのだから、f文字列を使うとコードがexpressive, terse, and clearになるということだ。<br />
「expressive」を引くと「表情豊かな・表現力豊かな」という訳語が出てくるが、コードの形容としてはあまり似合わない。</p>
<blockquote><p>Expressive suggests conveying, or being capable of conveying, a thought, intention, emotion, etc., in an effective or vivid manner: an expressive gesture.<br />
<a href="https://www.dictionary.com/browse/expressive">https://www.dictionary.com/browse/expressive</a></p></blockquote>
<p>という説明を見れば「expressive」の意味は「コードがその意図や処理内容を伝えられること」で、これclearと近い意味にならないか?<br />
うまい日本語訳が思い付かなかったので最終的な訳は確定できませんでした、ごめんなさい。</p>
<h3 id="p25-項目6">p.25 項目6</h3>
<p>日本語版:比較対照のため、アンパックを使わずにスナック食品リストの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C6%A5%EC%A1%BC%A5%B7%A5%E7%A5%F3">イテレーション</a>例を次に示します。<br />
原文:As an example for contrast, here I iterate over a list of snacks without using unpacking:</p>
<p>直訳:対比のための例として、以下で私はスナック食品のリストをアンパックを使わずにイテレートする。<br />
意訳:対比のため、スナック食品のリストをアンパックを使わずにイテレートする例を以下に示します。</p>
<p>「アンパックを使わずに」の文節はどこを修飾してるんだろうか?
唯一考えられるのは「示します」だが、「アンパックを使わずに示します」は奇妙だろう。
「イテレートする例」を「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C6%A5%EC%A1%BC%A5%B7%A5%E7%A5%F3">イテレーション</a>例」という名詞句にしてしまったため、「アンパックを使わずに」が修飾する先が消えてしまったのがここの問題である。</p>
<h3 id="p33-項目9">p.33 項目9</h3>
<p>日本語版:elseブロックによる表現性は、(自分も含めた)人が将来そのコードを理解するのに必要な負荷に値しません。 s</p>
<p>原文:However, the expressivity you gain from the else block doesn’t outweigh the burden you put on people (including yourself) who want to understand your code in the future.</p>
<p>間違いなくworthかdeserveを直訳したなと予想したが、原文はどっちでも無かった。なるほどoutweighなのか。<br />
「表現性」についてはすでに述べたので割愛。こっちはexpressivityかー。expressivityはそんなに大きくなく、burdenのほうが大きくなってしまうから、elseブロックを使うな、という話だから、以下のように意訳してみたが、どうでしょうか。<br />
目的語のburden ...という名詞句を日本語版でも名詞句で訳すから読みづらいのだと思う。適切に品詞を変換してほしい。</p>
<p>直訳:しかしながら、あなたがelseブロックから得る表現力は、将来あなたのコードを理解しようとする人(あなた自身も含む)にあなたが課す負担を上回らない。<br />
意訳:しかし、elseブロックを使ってしまうと、コードの意図が伝わりにくくなり、将来あなたのコードを理解しようとする人(あなた自身も含む)が苦労するというデメリットのほうが大きくなるのです。</p>
<h3 id="p36-項目10">p.36 項目10</h3>
<p>日本語訳:この第2の方式は、peices変数が初めて定義されるif文の各ブロックの異なる位置にあるので奇妙に感じます。</p>
<p>「peices変数が」の主語に対応する述語は何か? 「定義される」だと、後段の「ある」に対応する主語が無いのでおかしい。したがって「ある」と解釈するしかない。「初めて定義されるif文の各ブロックの異なる位置にpeices変数があるので」と同じということだ。</p>
<p>しかしそうなると「初めて定義されるif文」とは何だ? 能動態に直すと「(誰かが)初めてif文を定義する」である。いつ誰がif文を定義したんだ?<br />
疑問符が頭の中に浮かんできたところで原文を見ると、以下の通りである。</p>
<p>原文:This second approach can feel odd because it means that the pieces variable has two different locations—in each block of the if statement—where it can be initially defined.</p>
<p>だいぶ訳しにくい文章だね……because以下が長いので、ここで一旦文を切るのが良い。で、「different」は「分かれてしまう」でニュアンスを出した。日本語だと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%C3%A5%B7%A5%E5">ダッシュ</a>よりも括弧のほうが挿入句だと分かりやすいだろうと思ったので、そう変えてある。<br />
「where it can be initially defined」のitは「the pieces variable」を指すので、定義されるのはif文ではなくてpeices変数だ。それなら話が通じる。</p>
<p>直訳:この2番めの方法は、奇妙な感じがする。なぜなら、このやり方は、pieces変数が、それが最初に定義される可能性のある2つの異なる場所―すなわちif文の各ブロック―にあることを意味するからだ。<br />
意訳:この2番めの方法は、奇妙な感じがします。なぜなら、このやり方だと、pieces変数が最初に定義される可能性のある場所が2箇所(すなわちif文の各ブロック)に分かれてしまうことになるからです。</p>
<h2 id="第2章">第2章</h2>
<h3 id="p46-項目12">p.46 項目12</h3>
<p>日本語訳:スライスでは、正の増分値をstartやendのどちらか一方のみと使う。<br />
原文:Prefer using positive stride values in slices without start or end indexes.</p>
<p>without A or Bで「AもBも無しで」という意味になる。</p>
<p>直訳:正の増分値を、startやendのindexを使わずに使うこと。<br />
意訳:正の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%C8%A5%E9%A5%A4%A5%C9">ストライド</a>値をなるべく使うようにし、その場合はstartやendは使わないようにする。</p>
<p>「正の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%C8%A5%E9%A5%A4%A5%C9">ストライド</a>値を使い、startやendは使わないようにする。」と書こうかと思ったが、これだとstartやendをどんな時も使ってはいけないように読めてしまう(実際は違う)。難しいね。</p>
<p>日本語訳に対応する文章は
「Use positive stride values in slices <strong>with either start or end index.</strong>」である。これは誤訳と断じても良いだろう。</p>
<p>抜き出した箇所は項目のまとめの部分だが、少し上を見ると本文の中で「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%C8%A5%E9%A5%A4%A5%C9">ストライド</a>を使わなければいけないときは、できる限り正の値にして、startとendのインデックスを省きます。」と書いてある。こちらが正しく、私の翻訳とも符合する。</p>
<h3 id="p47-項目13">p.47 項目13</h3>
<p>日本語訳:このコードは短くて読みやすく、行間で同期しなければならない境界値エラーが生じる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>がなくなりました。</p>
<p>「行間で同期しなければならない」のは何なのか?「境界値エラー」か「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>」の二択だが、どっちも奇妙だ。「境界値エラーを行間で同期する」とは言わないだろう。通信処理ではないので「同期する」もパッと分かりづらく、この状況に合う語のほうが良い。</p>
<p>原文:This code is shorter, easier to read, and no longer has the error-prone brittleness of boundary indexes that must be kept in sync between lines.</p>
<p>直訳:このコードはより短く、より読みやすく、そしてもはやこのコードには、行間で一致させておかなければいけない境界のインデックスのエラーになりやすい<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>がない。<br />
意訳:このコードのほうが短く読みやすくなりました。そしてこのコードには、複数の行の間で境界のインデックスを整合せねばならず、エラーを引き起こしやすいという<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>がありません。</p>
<h3 id="p56-項目15">p.56 項目15</h3>
<p>日本語版:Python3.6、3.7以降は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>の仕様として、辞書は挿入順を保持するようになりました。<br />
原文:Starting with <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 3.6, and officially part of the <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> specification in version 3.7, dictionaries will preserve insertion order.</p>
<p>何気なく原著を眺めていて、この部分が誤訳だと知った。
(だいたいは日本語版を見て引っかかって確かめることが多いのだが、この文は全く見ても引っかかることがなかった。原著を見てビックリ、違う意味じゃないか。)</p>
<p>直訳:Python3.6から始まり、バージョン3.7では公式に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>仕様の一部であるが、辞書は挿入の順序を保持する。<br />
意訳:辞書は挿入の順序を保持するようになりました。これはPython3.6から始まり、バージョン3.7では公式に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>仕様の一部になりました。</p>
<p>(being) part of the ... とbeingが省略された構文と解釈した。</p>
<p>3.6では辞書は挿入の順序を保持するが、それは仕様に明記された動作ではない。(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>公式ドキュメントでは <a href="https://docs.python.org/ja/3/whatsnew/3.6.html#new-dict-implementation">What's New In Python 3.6 — Python 3.10.6 ドキュメント</a> にその旨の記載がある。)その後Python3.7で、
<a href="https://docs.python.org/ja/3/whatsnew/3.7.html">What's New In Python 3.7 — Python 3.10.6 ドキュメント</a>「dict オブジェクトの挿入順序を保存するという性質が、公式に <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 言語仕様の一部であると 宣言されました。」と公式な仕様になった。</p>
<p>日本語版を読んだ人は「3.6、3.7以降」が並列だと思うから、「Python3.6では、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>の仕様として、辞書は挿入した順序を保持する。」を正しいと思うだろう。自分の日本語読解能力に自信が無くなってきたので、同時に日本語訳の本を読み進めている友人に聞いてみたが、「正しいと思う」という答えが返ってきた。上記の通り、実際は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>の仕様でないから、正しくない。</p>
<h3 id="p57-項目15">p.57 項目15</h3>
<p>日本語訳:<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 3.5以前では、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C6%A5%EC%A1%BC%A5%B7%A5%E7%A5%F3">イテレーション</a>順序に依存するdictの全メソッドは、keys, values, items, popitemを含めて、同じようにランダムに見える振る舞いでした。</p>
<p>原著:With <a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 3.5 and earlier, all methods provided by dict that relied on iteration order, including keys, values, items, and popitem, would similarly demonstrate this random-looking behavior:</p>
<p>「同じようにランダムに見える振る舞い」が引っかかる。「keysの振る舞いはvaluesの振る舞いと同じようにランダムに見えるなぁ」という話か? ピンと来ない。原文は「similarly demonstrate」なので、「同様に示す」という修飾関係である。</p>
<p>including ... は「……などの」と例示で訳したほうが通りが良いと思う(参考:詳解 技術英文大全 第3巻 高度な英文表現 p.74)。直訳だといきなり具体的なメソッド名が出てくるので、意訳の方ではカッコに入れて後回しにしてみたけど、どう処理するのがいいんだろうか。</p>
<p>thisは多分「直後の例で示す通りの」という意味だと思うが、くどいので訳出しなかった。</p>
<p>直訳:<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 3.5以前では、keys, values, items, popitemなど、dictによって提供される、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C6%A5%EC%A1%BC%A5%B7%A5%E7%A5%F3">イテレーション</a>順序に依存する全てのメソッドは、ランダムに見える動作を同様に示していた。<br />
意訳:<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a> 3.5以前では、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%C6%A5%EC%A1%BC%A5%B7%A5%E7%A5%F3">イテレーション</a>順序に依存するdictのメソッド(keys, values, items, popitemなど)は全て同じように、ランダムに見える挙動をしていた。</p>
<h3 id="p66-項目16">p.66 項目16</h3>
<p>日本語版:もう1つ重要なことがあります。<br />
原著:There’s also one important gotcha:</p>
<p>あららら。gotchaを訳し飛ばしてる。俺が前に記事に書いたところじゃん。詳細は以下の記事を参照してください。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2F2019%2F11%2F17%2F000004" title="gotchaが名詞の場合の意味。 - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/2019/11/17/000004">linus-mk.hatenablog.com</a></cite></p>
<p>検索すると原著の全体の中で「gotcha」は12回使われている。日本語版では「理解すべきところ・予想しない動作」などの訳が多いが、訳が飛んでいるところも少しある。</p>
<p>直訳/意訳:もう1つ重要な落とし穴があります。</p>
<h2 id="第3章">第3章</h2>
<h3 id="p88-項目23">p.88 項目23</h3>
<p>日本語版:場合によっては、直近のセンサー測定値から、より長い時間尺度における時間あたりとか日あたりなどが役立つこともあるでしょう。<br />
原文:Other times, it’d be helpful to use the last sensor measurements to approximate larger time scales, like hours or days.</p>
<p>日本語版は非文だろう。日本語版を読んだ時点で何かがおかしいことがわかり、一体どうしたんだろうと心配になる。</p>
<p>え、これは自信がない……「like hours or days」が「1時間あたりや1日あたり」だとしたら、per hourだから単数形になるのでは。なんで複数形になってるんだろう。<br />
無冠詞複数形の「一般的なもの、不特定多数」の用法だろうか? 「数時間や数日」だとしたら「several hours or days」あたりになってないと不自然な気がする。分からん。分からないので、1時間・1日で訳します。</p>
<p>直訳:ある場合には、最近のセンサーの測定値を使うことでより大きな時間尺度、例えば1時間や1日を近似するほうが便利だろう。
意訳:ある場合には、最近のセンサーの測定値を使うことでより大きな時間尺度、例えば1時間や1日の値を近似するほうが便利だろう。</p>
<h3 id="p89-項目23">p.89 項目23</h3>
<p>日本語訳:関数を書く側としては、すべての呼び出し元で、より明確なキーワードスタイルを用いることでエラーの可能性を極力減らす必要があります(カッコ内は略)。<br />
原文:As a function author, you can also require that all callers use this more explicit keyword style to minimize potential errors (<em>snip</em>).</p>
<p>require S V(原型)で「SにVするよう命じる・要求する」です。
関数を書く人がキーワード専用引数を使えば、関数を呼び出す側に「引数を位置指定するな、絶対にキーワード方式で引数を指定しろ」と強制できるという話です。「要求する」だと要求に従わない場合もありそうなので、「強制」にしておこう。</p>
<p>直訳:関数を書く人として、あなたはすべての呼び出し元に、起こり得るエラーを最小化するためにこのより明確なキーワード方式を使うことを要求することもできる。<br />
意訳:関数を書く人は、すべての呼び出し元に、このより明確なキーワード方式を使ってエラーの可能性を最小化することを強制することもできます。</p>
<h3 id="p95-項目25">p.95 項目25</h3>
<p>日本語版:後で、拡張の必要性や好みが変わったために最初の2引数の名前を変える決定をしたとします。<br />
原文:Later, I may decide to change the names of these first two arguments because of expanding needs or even just because my style preferences change:</p>
<p>直訳:後に、拡張の必要性のせい、またはただ単に私のスタイルの好みが変わるせいでさえ、私はこれらの最初の2個の変数の名前を変更することに決めるかもしれない。<br />
意訳:将来、拡張の必要性が生じたせい、またはただ単にスタイルの好みが変わったせいで、これらの最初の2個の変数名を変更しようと決めるかもしれません。</p>
<p>この日本語訳だと「拡張の必要性が変わったために or 好みが変わったために」という解釈になると思うのだが。英語の名詞句を日本語の名詞句にそのまま翻訳するのは翻訳者の好みだけど、そのせいで文意が変わってくるのはよろしくないと思う……</p>
<hr />
<p>気力があったら書く</p>
<p>p.23
提供する</p>
<p>p.30
が、デフォルトはNoneに<br />
曖昧な接続助詞「が」。fillvalueとデフォルトが離れたのでどのデフォルトか分かりにくい。</p>
<p>p.52
重さでソートするラムダ関数も簡単に定義できて……(ラムダ関数はソートをしない)</p>
<p>p.52
ここで示したように(シーケンス、タプル、辞書では)……修飾関係がおかしい</p>
<p>p.57
一貫した挿入順序を提供</p>
<p>p.97 項目26
引数リストの1つの*の後として定義される。</p>
<p><a href="https://www.amazon.co.jp/Effective-Python-%E2%80%95Python%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E6%94%B9%E8%89%AF%E3%81%99%E3%82%8B90%E9%A0%85%E7%9B%AE-Brett-Slatkin/dp/4873119170/ref=as_li_ss_il?ie=UTF8&linkCode=li3&tag=limk-22&linkId=2a51865e1c1f7f08ba09a29035553721&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4873119170&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=limk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=limk-22&language=ja_JP&l=li3&o=9&a=4873119170" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
<a href="https://www.amazon.co.jp/Effective-Python-Specific-Software-Development/dp/0134853989/ref=as_li_ss_il?_encoding=UTF8&pd_rd_i=0134853989&pd_rd_r=d28c24ba-e01f-4735-af95-e659822ba92e&pd_rd_w=4SXlO&pd_rd_wg=rFVp3&pf_rd_p=4b55d259-ebf0-4306-905a-7762d1b93740&pf_rd_r=DNPBCCHKFVCMJNWN4N36&psc=1&refRID=DNPBCCHKFVCMJNWN4N36&linkCode=li3&tag=limk-22&linkId=454c72d4808babf409499868fb8d156a&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=0134853989&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=limk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=limk-22&language=ja_JP&l=li3&o=9&a=0134853989" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
soratokimitonoaidani
pandasのDataFrameをfloatからintに変換する方法
hatenablog://entry/26006613611729555
2020-08-08T20:32:50+09:00
2020-08-27T23:20:17+09:00 「pandas float int 変換」で検索する人が結構いるので、まとめておきます。 準備 1列だけをfloatからintに変換する 複数列をfloatからintに変換する すべての列をfloatからintに変換する 文字列とかがある場合は? NaNを含む場合は? int型で欠損値をNaNのままで扱う方法は 何でみんなこれで検索してるのか(read_csvでfloatになってしまった?) 準備 import pandas as pd import numpy as np pd.options.display.notebook_repr_html = False # jupyter note…
<p>「pandas float int 変換」で検索する人が結構いるので、まとめておきます。</p>
<ul class="table-of-contents">
<li><a href="#準備">準備</a></li>
<li><a href="#1列だけをfloatからintに変換する">1列だけをfloatからintに変換する</a></li>
<li><a href="#複数列をfloatからintに変換する">複数列をfloatからintに変換する</a></li>
<li><a href="#すべての列をfloatからintに変換する">すべての列をfloatからintに変換する</a></li>
<li><a href="#文字列とかがある場合は">文字列とかがある場合は?</a></li>
<li><a href="#NaNを含む場合は">NaNを含む場合は?</a></li>
<li><a href="#int型で欠損値をNaNのままで扱う方法は">int型で欠損値をNaNのままで扱う方法は</a></li>
<li><a href="#何でみんなこれで検索してるのかread_csvでfloatになってしまった">何でみんなこれで検索してるのか(read_csvでfloatになってしまった?)</a></li>
</ul>
<h2 id="準備">準備</h2>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd
<span class="synPreProc">import</span> numpy <span class="synStatement">as</span> np
pd.options.display.notebook_repr_html = <span class="synIdentifier">False</span> <span class="synComment"># jupyter notebook上での出力形式を制御するために書いています。無くても動きます。</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 動作環境の確認</span>
<span class="synIdentifier">print</span>(pd.__version__)
<span class="synIdentifier">print</span>(np.__version__)
<span class="synComment"># --------------------</span>
<span class="synConstant">1.0</span>.<span class="synConstant">5</span>
<span class="synConstant">1.18</span>.<span class="synConstant">1</span>
</pre>
<h2 id="1列だけをfloatからintに変換する">1列だけをfloatからintに変換する</h2>
<p>astype関数を使ってデータの型を変換すれば良い。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df = pd.DataFrame({
<span class="synConstant">'col_A'</span>: [<span class="synConstant">1.2</span> ,<span class="synConstant">3.4</span>, <span class="synConstant">5.6</span>],
<span class="synConstant">'col_B'</span>: [<span class="synConstant">9.8</span>, <span class="synConstant">7.6</span>, <span class="synConstant">5.4</span>],
<span class="synConstant">'col_C'</span>: [<span class="synConstant">11.1</span>, <span class="synConstant">22.2</span>, <span class="synConstant">33.3</span>],
<span class="synConstant">'col_D'</span>: [<span class="synConstant">99.9</span>, <span class="synConstant">88.8</span>, <span class="synConstant">77.7</span>]
})
df
<span class="synComment"># --------------------</span>
col_A col_B col_C col_D
<span class="synConstant">0</span> <span class="synConstant">1.2</span> <span class="synConstant">9.8</span> <span class="synConstant">11.1</span> <span class="synConstant">99.9</span>
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7.6</span> <span class="synConstant">22.2</span> <span class="synConstant">88.8</span>
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5.4</span> <span class="synConstant">33.3</span> <span class="synConstant">77.7</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df.dtypes
<span class="synComment"># --------------------</span>
col_A float64
col_B float64
col_C float64
col_D float64
dtype: <span class="synIdentifier">object</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df[<span class="synConstant">'col_B'</span>].astype(<span class="synConstant">'int'</span>)
<span class="synComment"># --------------------</span>
<span class="synConstant">0</span> <span class="synConstant">9</span>
<span class="synConstant">1</span> <span class="synConstant">7</span>
<span class="synConstant">2</span> <span class="synConstant">5</span>
Name: col_B, dtype: int64
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df[<span class="synConstant">'col_B'</span>] = df[<span class="synConstant">'col_B'</span>].astype(<span class="synConstant">'int'</span>)
df
<span class="synComment"># --------------------</span>
col_A col_B col_C col_D
<span class="synConstant">0</span> <span class="synConstant">1.2</span> <span class="synConstant">9</span> <span class="synConstant">11.1</span> <span class="synConstant">99.9</span>
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7</span> <span class="synConstant">22.2</span> <span class="synConstant">88.8</span>
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5</span> <span class="synConstant">33.3</span> <span class="synConstant">77.7</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df.dtypes
<span class="synComment"># --------------------</span>
col_A float64
col_B int64
col_C float64
col_D float64
dtype: <span class="synIdentifier">object</span>
</pre>
<h2 id="複数列をfloatからintに変換する">複数列をfloatからintに変換する</h2>
<p>1列の場合とほぼ同じ。列名の指定をリストに変えるだけで良い。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df = pd.DataFrame({
<span class="synConstant">'col_A'</span>: [<span class="synConstant">1.2</span> ,<span class="synConstant">3.4</span>, <span class="synConstant">5.6</span>],
<span class="synConstant">'col_B'</span>: [<span class="synConstant">9.8</span>, <span class="synConstant">7.6</span>, <span class="synConstant">5.4</span>],
<span class="synConstant">'col_C'</span>: [<span class="synConstant">11.1</span>, <span class="synConstant">22.2</span>, <span class="synConstant">33.3</span>],
<span class="synConstant">'col_D'</span>: [<span class="synConstant">99.9</span>, <span class="synConstant">88.8</span>, <span class="synConstant">77.7</span>]
})
df
<span class="synComment"># --------------------</span>
col_A col_B col_C col_D
<span class="synConstant">0</span> <span class="synConstant">1.2</span> <span class="synConstant">9.8</span> <span class="synConstant">11.1</span> <span class="synConstant">99.9</span>
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7.6</span> <span class="synConstant">22.2</span> <span class="synConstant">88.8</span>
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5.4</span> <span class="synConstant">33.3</span> <span class="synConstant">77.7</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df[[<span class="synConstant">'col_B'</span>, <span class="synConstant">'col_D'</span>]].astype(<span class="synConstant">'int'</span>)
<span class="synComment"># --------------------</span>
col_B col_D
<span class="synConstant">0</span> <span class="synConstant">9</span> <span class="synConstant">99</span>
<span class="synConstant">1</span> <span class="synConstant">7</span> <span class="synConstant">88</span>
<span class="synConstant">2</span> <span class="synConstant">5</span> <span class="synConstant">77</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df[[<span class="synConstant">'col_B'</span>, <span class="synConstant">'col_D'</span>]] = df[[<span class="synConstant">'col_B'</span>, <span class="synConstant">'col_D'</span>]].astype(<span class="synConstant">'int'</span>)
df
<span class="synComment"># --------------------</span>
col_A col_B col_C col_D
<span class="synConstant">0</span> <span class="synConstant">1.2</span> <span class="synConstant">9</span> <span class="synConstant">11.1</span> <span class="synConstant">99</span>
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7</span> <span class="synConstant">22.2</span> <span class="synConstant">88</span>
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5</span> <span class="synConstant">33.3</span> <span class="synConstant">77</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df.dtypes
<span class="synComment"># --------------------</span>
col_A float64
col_B int64
col_C float64
col_D int64
dtype: <span class="synIdentifier">object</span>
</pre>
<h2 id="すべての列をfloatからintに変換する">すべての列をfloatからintに変換する</h2>
<p>dfに直接astype関数を適用すれば良い。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df = pd.DataFrame({
<span class="synConstant">'col_A'</span>: [<span class="synConstant">1.2</span> ,<span class="synConstant">3.4</span>, <span class="synConstant">5.6</span>],
<span class="synConstant">'col_B'</span>: [<span class="synConstant">9.8</span>, <span class="synConstant">7.6</span>, <span class="synConstant">5.4</span>],
<span class="synConstant">'col_C'</span>: [<span class="synConstant">11.1</span>, <span class="synConstant">22.2</span>, <span class="synConstant">33.3</span>],
<span class="synConstant">'col_D'</span>: [<span class="synConstant">99.9</span>, <span class="synConstant">88.8</span>, <span class="synConstant">77.7</span>]
})
df
<span class="synComment"># --------------------</span>
col_A col_B col_C col_D
<span class="synConstant">0</span> <span class="synConstant">1.2</span> <span class="synConstant">9.8</span> <span class="synConstant">11.1</span> <span class="synConstant">99.9</span>
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7.6</span> <span class="synConstant">22.2</span> <span class="synConstant">88.8</span>
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5.4</span> <span class="synConstant">33.3</span> <span class="synConstant">77.7</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df.astype(<span class="synConstant">'int'</span>)
<span class="synComment"># --------------------</span>
col_A col_B col_C col_D
<span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">9</span> <span class="synConstant">11</span> <span class="synConstant">99</span>
<span class="synConstant">1</span> <span class="synConstant">3</span> <span class="synConstant">7</span> <span class="synConstant">22</span> <span class="synConstant">88</span>
<span class="synConstant">2</span> <span class="synConstant">5</span> <span class="synConstant">5</span> <span class="synConstant">33</span> <span class="synConstant">77</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df = df.astype(<span class="synConstant">'int'</span>)
df
<span class="synComment"># --------------------</span>
col_A col_B col_C col_D
<span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">9</span> <span class="synConstant">11</span> <span class="synConstant">99</span>
<span class="synConstant">1</span> <span class="synConstant">3</span> <span class="synConstant">7</span> <span class="synConstant">22</span> <span class="synConstant">88</span>
<span class="synConstant">2</span> <span class="synConstant">5</span> <span class="synConstant">5</span> <span class="synConstant">33</span> <span class="synConstant">77</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df.dtypes
<span class="synComment"># --------------------</span>
col_A int64
col_B int64
col_C int64
col_D int64
dtype: <span class="synIdentifier">object</span>
</pre>
<h2 id="文字列とかがある場合は">文字列とかがある場合は?</h2>
<p>文字列がある場合、文字列はintに変換することができない。
この場合、DataFrame全体に対して普通に<code>astype()</code>を適用するとエラーになってしまう。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df = pd.DataFrame({
<span class="synConstant">'col_A'</span>: [<span class="synConstant">1.2</span> ,<span class="synConstant">3.4</span>, <span class="synConstant">5.6</span>],
<span class="synConstant">'col_B'</span>: [<span class="synConstant">9.8</span>, <span class="synConstant">7.6</span>, <span class="synConstant">5.4</span>],
<span class="synConstant">'col_C'</span>: [<span class="synConstant">11.1</span>, <span class="synConstant">22.2</span>, <span class="synConstant">33.3</span>],
<span class="synConstant">'col_string'</span>: [<span class="synConstant">'hello'</span>, <span class="synConstant">'good_morning'</span>, <span class="synConstant">'good_night'</span>]
})
df
<span class="synComment"># --------------------</span>
col_A col_B col_C col_string
<span class="synConstant">0</span> <span class="synConstant">1.2</span> <span class="synConstant">9.8</span> <span class="synConstant">11.1</span> hello
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7.6</span> <span class="synConstant">22.2</span> good_morning
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5.4</span> <span class="synConstant">33.3</span> good_night
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df.astype(<span class="synConstant">'int'</span>)
<span class="synComment"># --------------------</span>
→エラー
</pre>
<p><details><summary>クリックするとエラー内容が開きます</summary><div></p>
<pre class="code" data-lang="" data-unlink> ValueError Traceback (most recent call last)
<ipython-input-17-d2a2db5e8de2> in <module>
----> 1 df.astype('int')
/usr/local/lib/python3.7/site-packages/pandas/core/generic.py in astype(self, dtype, copy, errors)
5696 else:
5697 # else, only a single dtype is given
-> 5698 new_data = self._data.astype(dtype=dtype, copy=copy, errors=errors)
5699 return self._constructor(new_data).__finalize__(self)
5700
/usr/local/lib/python3.7/site-packages/pandas/core/internals/managers.py in astype(self, dtype, copy, errors)
580
581 def astype(self, dtype, copy: bool = False, errors: str = "raise"):
--> 582 return self.apply("astype", dtype=dtype, copy=copy, errors=errors)
583
584 def convert(self, **kwargs):
/usr/local/lib/python3.7/site-packages/pandas/core/internals/managers.py in apply(self, f, filter, **kwargs)
440 applied = b.apply(f, **kwargs)
441 else:
--> 442 applied = getattr(b, f)(**kwargs)
443 result_blocks = _extend_blocks(applied, result_blocks)
444
/usr/local/lib/python3.7/site-packages/pandas/core/internals/blocks.py in astype(self, dtype, copy, errors)
623 vals1d = values.ravel()
624 try:
--> 625 values = astype_nansafe(vals1d, dtype, copy=True)
626 except (ValueError, TypeError):
627 # e.g. astype_nansafe can fail on object-dtype of strings
/usr/local/lib/python3.7/site-packages/pandas/core/dtypes/cast.py in astype_nansafe(arr, dtype, copy, skipna)
872 # work around NumPy brokenness, #1987
873 if np.issubdtype(dtype.type, np.integer):
--> 874 return lib.astype_intsafe(arr.ravel(), dtype).reshape(arr.shape)
875
876 # if we have a datetime/timedelta array of objects
pandas/_libs/lib.pyx in pandas._libs.lib.astype_intsafe()
ValueError: invalid literal for int() with base 10: 'hello'</pre>
<p></div></details></p>
<p>この場合でも全てのfloat型のデータをintにして、なおかつエラーにならない方法は、
<code>errors='ignore'</code>を指定することである。<br />
このオプションに関しては、pandasのdtypeの記事を参照のこと。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2F2019%2F11%2F23%2F162709" title="pandasのデータ型、dtypeについて 公式ドキュメントを翻訳した - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/2019/11/23/162709">linus-mk.hatenablog.com</a></cite></p>
<pre class="code lang-python" data-lang="python" data-unlink>df.astype(<span class="synConstant">'int'</span>, errors=<span class="synConstant">'ignore'</span>)
<span class="synComment"># --------------------</span>
col_A col_B col_C col_string
<span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">9</span> <span class="synConstant">11</span> hello
<span class="synConstant">1</span> <span class="synConstant">3</span> <span class="synConstant">7</span> <span class="synConstant">22</span> good_morning
<span class="synConstant">2</span> <span class="synConstant">5</span> <span class="synConstant">5</span> <span class="synConstant">33</span> good_night
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df = df.astype(<span class="synConstant">'int'</span>, errors=<span class="synConstant">'ignore'</span>)
df.dtypes
<span class="synComment"># --------------------</span>
col_A int64
col_B int64
col_C int64
col_string <span class="synIdentifier">object</span>
dtype: <span class="synIdentifier">object</span>
</pre>
<h2 id="NaNを含む場合は">NaNを含む場合は?</h2>
<p>DataFrame内部にNaNを含む場合も、DataFrame全体に対して普通に<code>astype()</code>を適用するとエラーになってしまう。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df = pd.DataFrame({
<span class="synConstant">'col_A'</span>: [<span class="synConstant">1.2</span> ,<span class="synConstant">3.4</span>, <span class="synConstant">5.6</span>],
<span class="synConstant">'col_B'</span>: [np.nan, <span class="synConstant">7.6</span>, <span class="synConstant">5.4</span>],
<span class="synConstant">'col_C'</span>: [<span class="synConstant">11.1</span>, <span class="synConstant">22.2</span>, <span class="synConstant">33.3</span>],
<span class="synConstant">'col_D'</span>: [<span class="synConstant">99.9</span>, np.nan, <span class="synConstant">77.7</span>]
})
df
<span class="synComment"># --------------------</span>
col_A col_B col_C col_D
<span class="synConstant">0</span> <span class="synConstant">1.2</span> NaN <span class="synConstant">11.1</span> <span class="synConstant">99.9</span>
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7.6</span> <span class="synConstant">22.2</span> NaN
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5.4</span> <span class="synConstant">33.3</span> <span class="synConstant">77.7</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df.astype(<span class="synConstant">'int'</span>)
<span class="synComment"># --------------------</span>
→エラー
</pre>
<p><details><summary>クリックするとエラー内容が開きます</summary><div></p>
<pre class="code" data-lang="" data-unlink> ValueError Traceback (most recent call last)
<ipython-input-21-d2a2db5e8de2> in <module>
----> 1 df.astype('int')
/usr/local/lib/python3.7/site-packages/pandas/core/generic.py in astype(self, dtype, copy, errors)
5696 else:
5697 # else, only a single dtype is given
-> 5698 new_data = self._data.astype(dtype=dtype, copy=copy, errors=errors)
5699 return self._constructor(new_data).__finalize__(self)
5700
/usr/local/lib/python3.7/site-packages/pandas/core/internals/managers.py in astype(self, dtype, copy, errors)
580
581 def astype(self, dtype, copy: bool = False, errors: str = "raise"):
--> 582 return self.apply("astype", dtype=dtype, copy=copy, errors=errors)
583
584 def convert(self, **kwargs):
/usr/local/lib/python3.7/site-packages/pandas/core/internals/managers.py in apply(self, f, filter, **kwargs)
440 applied = b.apply(f, **kwargs)
441 else:
--> 442 applied = getattr(b, f)(**kwargs)
443 result_blocks = _extend_blocks(applied, result_blocks)
444
/usr/local/lib/python3.7/site-packages/pandas/core/internals/blocks.py in astype(self, dtype, copy, errors)
623 vals1d = values.ravel()
624 try:
--> 625 values = astype_nansafe(vals1d, dtype, copy=True)
626 except (ValueError, TypeError):
627 # e.g. astype_nansafe can fail on object-dtype of strings
/usr/local/lib/python3.7/site-packages/pandas/core/dtypes/cast.py in astype_nansafe(arr, dtype, copy, skipna)
866
867 if not np.isfinite(arr).all():
--> 868 raise ValueError("Cannot convert non-finite values (NA or inf) to integer")
869
870 elif is_object_dtype(arr):
ValueError: Cannot convert non-finite values (NA or inf) to integer</pre>
<p></div></details></p>
<p><code>errors='ignore'</code>を指定しても、期待した通りの動作にならない。これは文字列が入っている場合と違う挙動だ。</p>
<pre class="code lang-python" data-lang="python" data-unlink>df.astype(<span class="synConstant">'int'</span>, errors=<span class="synConstant">'ignore'</span>)
<span class="synComment"># --------------------</span>
col_A col_B col_C col_D
<span class="synConstant">0</span> <span class="synConstant">1.2</span> NaN <span class="synConstant">11.1</span> <span class="synConstant">99.9</span>
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7.6</span> <span class="synConstant">22.2</span> NaN
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5.4</span> <span class="synConstant">33.3</span> <span class="synConstant">77.7</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df.astype(<span class="synConstant">'int'</span>, errors=<span class="synConstant">'ignore'</span>).dtypes
<span class="synComment"># --------------------</span>
col_A float64
col_B float64
col_C float64
col_D float64
dtype: <span class="synIdentifier">object</span>
</pre>
<p>……謎の挙動してるな。<br />
文字列の場合と同じく、「nanを含まない<code>col_A</code>, <code>col_C</code>は整数になり、nanを含む列はfloatのまま」になるのかと思ったよ。<br />
そうじゃないんだな。何故か全ての列がそのままですね。何でだろう。</p>
<p>……というわけで<code>errors='ignore'</code>を使うとエラーは出ませんが目的は達成できません。<br />
正解は、fillna関数を使って欠損値NaNを埋めてからdtypeをintに変換することである。<br />
(fillna関数の引数を使うと、欠損値を埋める方法は色々指定できる。しかし、この記事の主眼ではないので、割愛する。公式ドキュメントを参照のこと。)</p>
<p><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html">pandas.DataFrame.fillna — pandas 1.1.0 documentation</a></p>
<pre class="code lang-python" data-lang="python" data-unlink>df.fillna(<span class="synConstant">0</span>)
<span class="synComment"># --------------------</span>
col_A col_B col_C col_D
<span class="synConstant">0</span> <span class="synConstant">1.2</span> <span class="synConstant">0.0</span> <span class="synConstant">11.1</span> <span class="synConstant">99.9</span>
<span class="synConstant">1</span> <span class="synConstant">3.4</span> <span class="synConstant">7.6</span> <span class="synConstant">22.2</span> <span class="synConstant">0.0</span>
<span class="synConstant">2</span> <span class="synConstant">5.6</span> <span class="synConstant">5.4</span> <span class="synConstant">33.3</span> <span class="synConstant">77.7</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>df.fillna(<span class="synConstant">0</span>).astype(<span class="synConstant">'int'</span>, errors=<span class="synConstant">'ignore'</span>)
<span class="synComment"># --------------------</span>
col_A col_B col_C col_D
<span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">11</span> <span class="synConstant">99</span>
<span class="synConstant">1</span> <span class="synConstant">3</span> <span class="synConstant">7</span> <span class="synConstant">22</span> <span class="synConstant">0</span>
<span class="synConstant">2</span> <span class="synConstant">5</span> <span class="synConstant">5</span> <span class="synConstant">33</span> <span class="synConstant">77</span>
</pre>
<h2 id="int型で欠損値をNaNのままで扱う方法は">int型で欠損値をNaNのままで扱う方法は</h2>
<p>「データ型をintにしたい」と「欠損値をそのまま(他の値で埋めずにNaNのままで)扱いたい」を両立する方法はないのだろうか?<br />
古いデータ型では、これを両方満たすものは無い。
比較的最近になって、これを両方満たすためのデータ型が誕生した。<br />
pandas 0.24.0 で導入された新しめの機能なので、私もよく分かっていない。
experimental(実験的機能)であり、今後仕様が変更される可能性もあるという注意書きがあるので、まだ本格的に使うには早いのかなと思う。</p>
<p><a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/integer_na.html">Nullable integer data type — pandas 1.1.1 documentation</a></p>
<h2 id="何でみんなこれで検索してるのかread_csvでfloatになってしまった">何でみんなこれで検索してるのか(read_<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>でfloatになってしまった?)</h2>
<p>おそらく、read_<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>関数で欠損値があるデータを読み込んだら、データがintのはずなのにfloatになってしまったのではないかと推測する。<br />
このあたりを参照。</p>
<p><a href="https://qiita.com/kuedasmn/items/6861a28685802b5fba69">pandas.read_csvの型がころころ変わる件 - Qiita</a><br />
<a href="https://ikatakos.com/pot/programming/python/packages/pandas/reduce_memory#dtypes">DataFrame読込時のメモリを節約 - pandas [いかたこのたこつぼ]</a></p>
<hr />
<p>今回の記事は以下のStakOverflowを参考にしました。</p>
<p><a href="https://stackoverflow.com/questions/21291259/convert-floats-to-ints-in-pandas">python - Convert floats to ints in Pandas? - Stack Overflow</a></p>
<p>それでは。</p>
soratokimitonoaidani
松岡亮二「教育格差」読書感想文
hatenablog://entry/26006613604706235
2020-07-26T12:56:54+09:00
2020-08-28T21:37:33+09:00 松岡亮二「教育格差」(ちくま新書)を読んだので、感想文を書く。 何についての本かというと、「出身家庭と地域という本人にはどうしようもない初期条件によって子供の最終学歴は異なり、それは 収入・職業・健康など様々な格差の基盤となる(表紙裏の概要より)」という話である。 いやぁ、いい本だった。おすすめである。 何で読んだの 圧倒的なデータによる徹底的な分析、大量の参考文献 近い本:中室牧子「学力の経済学」、パットナム「われらの子ども」 私の中学高校と、大学入学式の話 中高の学校ランク・学校SESと、進学熱・教育熱の関係。私は歌を聞いていたのだ。 とはいえ、どこで差を縮められる? 提言 その他で特筆す…
<p>松岡亮二「教育格差」(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%C1%A4%AF%A4%DE%BF%B7%BD%F1">ちくま新書</a>)を読んだので、感想文を書く。
何についての本かというと、「出身家庭と地域という本人にはどうしようもない初期条件によって子供の最終学歴は異なり、それは
収入・職業・健康など様々な格差の基盤となる(表紙裏の概要より)」という話である。
いやぁ、いい本だった。おすすめである。</p>
<p><a href="https://www.amazon.co.jp/%E6%95%99%E8%82%B2%E6%A0%BC%E5%B7%AE-%E3%81%A1%E3%81%8F%E3%81%BE%E6%96%B0%E6%9B%B8-%E6%9D%BE%E5%B2%A1-%E4%BA%AE%E4%BA%8C/dp/4480072373/ref=as_li_ss_il?_encoding=UTF8&qid=&sr=&linkCode=li3&tag=limk-22&linkId=078f7d81fa46ad496a88a71f609374b2&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4480072373&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=limk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=limk-22&language=ja_JP&l=li3&o=9&a=4480072373" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
<ul class="table-of-contents">
<li><a href="#何で読んだの">何で読んだの</a></li>
<li><a href="#圧倒的なデータによる徹底的な分析大量の参考文献">圧倒的なデータによる徹底的な分析、大量の参考文献</a></li>
<li><a href="#近い本中室牧子学力の経済学パットナムわれらの子ども">近い本:中室牧子「学力の経済学」、パットナム「われらの子ども」</a></li>
<li><a href="#私の中学高校と大学入学式の話">私の中学高校と、大学入学式の話</a></li>
<li><a href="#中高の学校ランク学校SESと進学熱教育熱の関係私は歌を聞いていたのだ">中高の学校ランク・学校SESと、進学熱・教育熱の関係。私は歌を聞いていたのだ。</a></li>
<li><a href="#とはいえどこで差を縮められる">とはいえ、どこで差を縮められる?</a></li>
<li><a href="#提言">提言</a></li>
<li><a href="#その他で特筆すべきところ">その他で特筆すべきところ</a></li>
<li><a href="#まとめ">まとめ</a></li>
</ul>
<h2 id="何で読んだの">何で読んだの</h2>
<p><a href="https://linus-mk.hatenablog.com/entry/2020_1Q_covid-19">新型コロナウイルスの感染拡大下の2020年4〜6月の生活の感想 - 子供の落書き帳 Renaissance</a>の中で書いたとおり、4月上旬に出社したときに
「どうせ書店もしばらく閉鎖するだろうし、本も買えなくなる」と思い、帰りに大型書店に寄って本を買った。<br />
閉店間際の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%AA%B0%CB%D4%A2%B2%B0%BD%F1%C5%B9">紀伊國屋書店</a>で、じっくり選ぶ時間も無いので、新書大賞の特集棚からエイッと決めた。<br />
そう、この本は新書大賞2020で3位に入賞している。<br />
<a href="https://www.chuko.co.jp/special/shinsho_award/">新書大賞|特設ページ|中央公論新社</a><br />
こういう貧困とか格差とかそういう話が割と好きなんですよね。<br />
自粛期間中に読もうと思ったくせに、読み終わるのに7月下旬までかかったわけだが……</p>
<h2 id="圧倒的なデータによる徹底的な分析大量の参考文献">圧倒的なデータによる徹底的な分析、大量の参考文献</h2>
<p>表紙裏の概要には
「本書は、戦後から現在までの動向、就学前〜高校までの各教育段階、国際比較と、教育格差の実態を
圧倒的なデータ量で検証。」と書いてある。
その言葉に間違いはない。<br />
印象論を完全に排除して、完璧にデータで押してくる本。
図表とグラフの量がとても多く、他の新書でこの本に比肩するものはだいぶ少ないだろう。<br />
個別の例に関しては存在を認めつつも、あくまで冷静に全体傾向をデータから描き出している。
つまり、以下のような論調である。
「親が学歴が低くて貧しい家であっても、子供が成績が良くて大学まで行った例もあるので、探せば見つかるだろう。だが、親の家庭環境が子どもの学歴や成績に影響するという全体傾向が厳然としてあることは変わらない」</p>
<p>あと参考文献の量が凄い。21ページあります。
「参考文献をしっかり書いている本は良書」が私の持論だが、その通りの結果である。</p>
<p>新書として並外れて分厚い・脚注の量がすごい(325箇所)・参考文献の量がすごい。
総じて新書とは思えないというか、よく新書で出版しようと思ったな、という感想。論文だと思ったほうが良いです。</p>
<h2 id="近い本中室牧子学力の経済学パットナムわれらの子ども">近い本:中室牧子「学力の経済学」、パットナム「われらの子ども」</h2>
<p>私がよく知っている中で近い本(というか引用されてる本)は、中室牧子「学力の経済学」、ロバート・パットナム「われらの子ども」。</p>
<p>中室牧子「学力の経済学」はビジネス書大賞2016年の準大賞を獲得したこともあり、知っている人も多いかもしれない。
(<a href="http://biztai.jp/2016/prize.html">ビジネス書大賞</a>)<br />
「教育格差」巻末の謝辞を見ると、松岡亮二と中室牧子とは一緒に研究した関係のようだ。</p>
<p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BC%D2%B2%F1%B4%D8%B7%B8%BB%F1%CB%DC">社会関係資本</a>、家庭の階級による子供の違いを(こちらはデータと具体例の両面から)記述したのが、ロバート・パットナムの「われらの子ども」である。こちらは教育に限らずもっと広い範囲を扱っているので、併せて読むと少し違った視点を得られるだろう。<br />
「われらの子ども」すみません……ちょうど1年ほど前に買ったは良いけど、読まずに積みっぱなしです……下の記事でも引き合いに出したけど、相変わらず未読です……だってあまりにもデカくて分厚いんだもの……すみません……</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flinus-mk.hatenablog.com%2Fentry%2Fbook_reportage_trump" title="金成隆一「ルポ トランプ王国」読書感想文 アメリカン・ドリームの終焉 - 子供の落書き帳 Renaissance" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://linus-mk.hatenablog.com/entry/book_reportage_trump">linus-mk.hatenablog.com</a></cite></p>
<h2 id="私の中学高校と大学入学式の話">私の中学高校と、大学入学式の話</h2>
<p>「教育格差」では一部の極端な例を出して格差を実際よりも誇張して大きく見せることを避けて、かなり大きな割合で区切った上で分析をしている。
両親のうち大卒が何人かで3つに切ったり(各分類の割合は25〜40%程度)、偏差値60以上の区分に注目したり(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%CA%AC%C9%DB">正規分布</a>で上位16%程度)といったところである。</p>
<p>自分自身を振り返ると、明らかに「一部の極端な例」に該当する中学高校生活を送った。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B3%AB%C0%AE%C3%E6%B3%D8">開成中学</a>/高等学校というところに行っていた。<br />
<a href="https://kaiseigakuen.jp/career/result-univ/">https://kaiseigakuen.jp/career/result-univ/</a> によれば、
1学年の400人中、現役で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%EC%B5%FE%C2%E7%B3%D8">東京大学</a>に合格した人は約120人、浪人後に合格する人も含めれば半数弱が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%EC%B5%FE%C2%E7%B3%D8">東京大学</a>に通うという状況である。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%EC%B5%FE%C2%E7%B3%D8">東京大学</a>の入学式は毎年、武道館で行われる。私が入学式に出席した時の細かいことは忘れてしまったが、1つの光景をよく覚えている。<br />
式典の前だか後だったか、自然に開成出身の同級生たちが自然に集まり始めた。
よぉ、お前もか、久しぶり、元気か、などと友人同士が会話を始めるうちに、開成出身の東大新入生はどんどん大きな集団になってきた。<br />
そこに目をつけたテレビ局の人が、「皆さん何してるんですか?撮らせてもらってもいいですか?」と寄ってきた。<br />
武道館の階段に並んで、テレビ局の人の指示に従い、一斉に「ズームイン!」と叫んで、私の大学生活はスタートした。確か、番組の「東大に合格した人にインタビューしました」コーナーの、最初の場面に使われたはずだ。</p>
<h2 id="中高の学校ランク学校SESと進学熱教育熱の関係私は歌を聞いていたのだ">中高の学校ランク・学校SESと、進学熱・教育熱の関係。私は歌を聞いていたのだ。</h2>
<p>「教育格差」の後半では学年が進んで、高校における教育格差を、膨大なデータから論じている。
ここではこの中で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%CA%B3%D8%B9%BB">進学校</a>とSESの関係を取り上げる。</p>
<p>SESはsocioeconomic statusの略で、日本語に訳すと「社会経済的地位」である。</p>
<p>まず、「高SES校」と「高ランク校」という概念を整理しよう。<br />
やや乱暴に言うと、<br />
「金持ちの高学歴両親の家庭の子供達が集まっている学校」=「高SES」<br />
「生徒の成績が良い学校」=「高ランク」<br />
である。
そして想像できるかもしれないが、この2つの学校は重なり合っている(pp.202-207)。</p>
<p>だが、この2つの影響をごっちゃにするな、分けて考えろ、と筆者は言う。
すなわち、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%CA%B3%D8%B9%BB">進学校</a>の人たちは「塾・予備校に通って大学に行く」傾向にあるが、その原因が「生徒の能力(=高ランク)」だけだと考えるのは不適切だという。原因として、「生徒の生まれ(=高SES)」を見落としているからだ。「頭がいいので塾・予備校に通って大学に行く」というのは真実だが、一面の真実でしか無い、と筆者は指摘する。<br />
学校ランク(生徒の学力)などいろいろな影響を除外して分析しても、高SES(生徒の家庭が高学歴高収入であること)だと</p>
<ul>
<li>大学進学しようと考える人の割合が高い(p.210)
<a href="#f-3bc8abca" name="fn-3bc8abca" title="これは「進学期待」であって、実際に進学したかどうかでは無い。本当はそれが一番確実な結果ではないかと思うけど、おそらくデータの制約から不可能だったと推察される。大学に行ったか、浪人→大学のルートも考えれば、高校生の集団を数年間追跡調査しなければいけないから。">*1</a></li>
<li>塾や予備校に通う人の割合が高い(p.212)</li>
<li>生徒の学習努力量が多い(p.214)</li>
</ul>
<p>という傾向が分かる。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%CA%B3%D8%B9%BB">進学校</a>の生徒は、高学力の影響に加えて、高SESの影響も受けることになる。
筆者の松岡亮二はこれを「教育熱のサウナ」と表現している。</p>
<p>「たとえるなら、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%CA%B3%D8%B9%BB">進学校</a>は制度的に作り上げられた教育熱のサウナだ。高SES家庭の生徒が集まることで、個人の学力とSESを超えた集合的な特性が学校外で学習機会を得ることを促していると考えられる。 p.212」<br />
「入学後3ヶ月の時点で、高ランク・高SES校の生徒は通塾・予備校通いをはじめる。学校ランクとは別に、学校SESは生徒の通塾・予備校通いを促している。この傾向は、高SES校に通う高SESの生徒に見られる。恵まれた「生まれ」の生徒たちが物理的に同じ場に集められることで、熱が高まると解釈できる。 p.<a class="keyword" href="http://d.hatena.ne.jp/keyword/226">226</a>」</p>
<p>私はこれを読んだとき、別の本のことを思い出した。人の生涯の様々な部分を科学的観点から論じた、デイヴィッド・<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D6%A5%EB%A5%C3%A5%AF%A5%B9">ブルックス</a>「あなたの人生の科学」である。</p>
<p>フィクションの中で、ある女子が「貧困家庭の生徒が勉強するための学校」に入学する。その学校の様子を描写したのが次のシーンだ。</p>
<blockquote><p>その他、歌う機会が多いということにも驚いた。……(中略)「大学の歌」というのもあった。有名大学の名前を次々にあげ、必ずそのどれかに入学すると誓う歌だ。集会の最後には、体育の教師が生徒たちに問いかける。「君たちはなぜここにいる?」生徒たちは答える。「教育を受けるため!」「君たちは何をする?」「勉強!」「君たちに大事なことは?」「努力!」「それと?」「規律!」「君たちはどこへ行く?」「大学!」「何のため?」「自分の未来を自分で決めるため!」「どうすれば大学に行ける!」「行けるようにすれば行ける!」「不可能はあるか?」「ない!」 <br />
(あなたの人生の科学 上 pp.236-237)</p></blockquote>
<p>最初にこの部分を読んだときに俺は「何だ、この歌wウケるww」と一笑に付していた。
しかし、「教育格差」の上掲部分を読んで、初めて腑に落ちた。</p>
<p><strong>中学高校時代の俺は、この歌を6年間歌って聞きながら過ごしていたのだ!</strong></p>
<p>もちろん、物理的に歌を歌ったわけではない。
が、学校の外でも勉強するのが自然だ、勉強して大学に進学するのが自然だ、という<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%AC%C8%CF%B0%D5%BC%B1">規範意識</a>は、高い学校ランクと高い学校SESを通じて入ってきた。そして俺の身体に染み込んだのだ。俺は「教育熱のサウナ」の中で、この歌を聞きながら過ごしていたのだ。</p>
<p>そして、逆も正しい。
低ランク・低SES校では、(何もしなければ)たぶん俺が開成で聞いたのとは逆の歌が流れている。(何もしなければ)異なる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%AC%C8%CF%B0%D5%BC%B1">規範意識</a>が浸透していくはずだ。<br />
貧困家庭のための学校では、生徒たちは高SESの恵みを享受することができないから、
「貧困家庭の親が無意識のうちに与えている悪影響を消す(あなたの人生の科学 上 p.230)」ためにこの歌が必要なのだ。初めてこの歌の存在意義が分かった。</p>
<h2 id="とはいえどこで差を縮められる">とはいえ、どこで差を縮められる?</h2>
<p>生まれが良くないというだけで子供の教育の様々な部分に悪い影響があり、最終的に子供の可能性が制限される。それが今の日本で起きていることだ。(日本だけではなく世界各国で同様だ。)<br />
そう言われたら、そういう格差が起きている状況は良くないね、是正したいね、とは確かに思う。 </p>
<p>だがしかし、年収と学業の達成はかなり密接に関係しているのではないか?<br />
以下の論法は異を唱える人はあまりいない気がする。</p>
<ul>
<li>世の中には、豊かな親と貧しい親、収入の高い親と低い親がいます。(資本主義社会なら必ずそうだろう。)</li>
<li>収入の高い親は、低い親と比べて多くの金を教育費に使えます。(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%C4%BD%E8%CA%AC%BD%EA%C6%C0">可処分所得</a>が多いのだから、そうだろう。)</li>
<li>親が多くの金を教育費に使い、子供を塾や予備校に行かせると、子供の成績は上がります。(塾講師や家庭教師のバイトをしてたから分かるが、バイトであってもなかなか一生懸命やってるんだから、その学力向上効果が皆無ということは無いだろう。プロの講師ならなおさらである。)</li>
<li>したがって、収入の高い親の子供のほうが、上位校に入学できます。(学力による選抜があるのならば、そうだろう。)</li>
</ul>
<p>……とここまで、至極当然の話ではないか? 一体どの部分に介入すれば、この傾向を解消できるのだ?<br />
だいたいは、低収入の家庭の子供で学習努力量がおなじになるように介入するんだと思うけど、塾や予備校の費用を誰かが出してくれるのか? 誰が何のために?</p>
<p>確かに教育経済学の研究では、子供が小さいうち、生まれてまもなく〜小学校より前のほうが中学高校よりも収益率が高いことが知られている(中室牧子「学力の経済学」pp. 75-82)。じゃあ中学高校になったら無対策で良いのだろうか?<br />
高校受験・大学受験ともなれば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BC%F5%B8%B3%BB%BA%B6%C8">受験産業</a>が存在してるから、高収入の親はガンガン金をつぎ込んで成績上昇に繋げられるはずなのだが?</p>
<p>ふえーーどうすれば現状改善をできるのか分からん。(思考の放棄)</p>
<h2 id="提言">提言</h2>
<p>本書の第7章では、筆者から2つの提案がなされている。
その内容は『〈提案1〉分析可能なデータを収集する』『〈提案2〉教職課程で「教育格差」を必修に!』
と、一見すると小粒だ。あれれ、ここまでゴリゴリ分析しまくったのに、教育の制度や政策をこうするべし! って話は出てこないの?<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/Amazon">Amazon</a>で「上位の批判的レビュー」を見ると、この点を批判しているレビューが見つかる。
<a href="https://www.amazon.co.jp/gp/customer-reviews/R21I3OG1IA5FR9/ref=cm_cr_arp_d_viewpnt?ie=UTF8&ASIN=B07TXTSD3G">矮小な提案と著者の自己発揚にとどまってしまった</a>
しかし、提言のスケールが小さいことを批判するのは早合点だと思う。</p>
<p>本をちゃんと読めば、大きな提案をぶちあげられない理由は分かる。以下2点だ。</p>
<p><strong>安易な政策・制度の提案ができない理由の1つ目。</strong><br />
2つの提案の前に、「最低限踏まえておきたい、まっとうな議論を可能とする4ヵ条(p.257)」をまとめている。以下の通りだ。</p>
<ol>
<li>価値・目標・機能の自覚化</li>
<li>「同じ扱い」だけでは格差を縮小できない現実</li>
<li>教育制度の選抜機能</li>
<li>データを用いて現状と向き合う</li>
</ol>
<p>詳しくは本書を参照してほしい。<br />
1番目にあるのが、「価値の相克の中で、どちらに進むのか自覚しよう」という話だ。</p>
<p>価値の相克。
相克とは聞き慣れない言葉だが、</p>
<blockquote><p>相克(そうこく) 対立・矛盾する二つのものが互いに相手に勝とうと争うこと。「理性と感情が―する」<br />
<a href="https://kotobank.jp/word/%E7%9B%B8%E5%85%8B-552269">https://kotobank.jp/word/%E7%9B%B8%E5%85%8B-552269</a></p></blockquote>
<p>である。<br />
別の言い方をすれば、あちらを立てればこちらが立たず、<strong><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%EC%A1%BC%A5%C9%A5%AA%A5%D5">トレードオフ</a></strong>の状態だ。(具体的にどんな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%EC%A1%BC%A5%C9%A5%AA%A5%D5">トレードオフ</a>なのかはここでは割愛……)</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%EC%A1%BC%A5%C9%A5%AA%A5%D5">トレードオフ</a>がある以上、何らかの対処は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%EC%A1%BC%A5%C9%A5%AA%A5%D5">トレードオフ</a>の上をどちらかに移動するものだから、どちらかが犠牲になるのだ。
対策は利点もあれば欠点もあるものになる。メリット100%の魔法のアイディアは存在しない。<br />
「一つの実践・政策・制度では、どちらかを重視すると、一方を軽視することになる(p.260)」
と本書にもハッキリ書いてあるのだ。<br />
ここまで書いた後に「一見良さそうな実践・政策・制度」を出したら自己矛盾に陥ってしまうだろう!
ここを読めば、安易な政策・制度の提案ができない理由が分かるだろう。</p>
<p><strong>安易な政策・制度の提案ができない理由の2つ目。</strong><br />
それは上記の「最低限踏まえておきたい、まっとうな議論を可能とする4ヵ条(p.257)」の4つ目に書いてある。<strong>データ不足の問題だ。</strong><br />
本書では、一貫してデータを使って論じてきた。
「こうすればいいよー」という、何らかの方策をポンと書くのは難しくない。
しかし、やった結果としてどのような成果が生まれるのか、それを言えるデータが揃っていないのが現状だからだ。
「言うは易し、行った効果を測定するのは難し」という状況なのだ。<br />
だから「(安易な政策・制度をする前に)まずデータをちゃんと取る体制を作らなきゃ」が提言に来るのだ。<br />
「やった効果測定が困難」なので、土台が整っていないのだから、議論のスタートラインに立てていない状態なのだ。</p>
<p>データの不足と軽視を論じるとき、筆者の舌鋒はひときわ鋭くなっていると思う。それはすなわち現状、教育に関する意思決定をデータに基づかずに実施してきたからである。<br />
今まで実施してきた教育制度の変更(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%E6%A4%C8%A4%EA%B6%B5%B0%E9">ゆとり教育</a>、高校教育改革など)に対しても
「本来であれば、政策変更前から研究者が分析を前提としたデータ収集計画を立て、(中略)効果検証をすべきだったのに、そういう体制にはなっていない。(p.292)」としている。<br />
現状は「実践と政策のやりっ放しで何がどうなっているのかよくわからない大海原を海図も<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%F4%C2%E6">灯台</a>も方位磁石もないままただひたすらに櫂を漕ぐ状態(p.302)」であると批判する。</p>
<p>しかしこの批判には見覚えがある。中室牧子「学力の経済学」でも見たのだ。ここまで辛辣ではないが、日本のデータが足りないので分析が十分にできず、効果が測定できていない現状を批判している(p137, p158など)。</p>
<p>中室牧子「学力の経済学」が出たのは2015年、松岡亮二が「教育格差」を出版したのは2019年。4年の年月が経っても同じ批判が繰り返されているところを見ると、事態があまり好転していないようだ。</p>
<p>多分日本はデータを軽視する社会な気がするし<a href="#f-bfd015fe" name="fn-bfd015fe" title="すみませんこれを立証するデータはありません……個人的な感覚論です……">*2</a>、これからもこの調子で「実践と政策のやりっ放しで何がどうなっているのかよくわからない」なるんでしょうね……(遠い目)</p>
<h2 id="その他で特筆すべきところ">その他で特筆すべきところ</h2>
<p>書くのに疲れてきたのでここは箇条書きで……</p>
<ul>
<li><p>本書への反論を予想してそこへの答えを書いてくるやつ、最高。「いやこれをちゃんと読み解ける人って高学歴の人が多いんじゃ……このメッセージが届くのは高学歴高SESだけじゃないか」と思っていましたが、「おわりに」で言及があります。</p></li>
<li><p>幼児期の時間の使い方を調べる、アネット・ラローの研究。この名前を知ったのは初めてだが、以前読んでたわ。読み返したらマルコム・グラッドウェル「天才!」第5章と「あなたの人生の科学 上」のpp.216-217で出てたわ。</p></li>
<li><p>小学校の習い事は学業達成に好ましいもの、高校生のアルバイトは学業達成に好ましくないものと、正反対として扱われているのが気になる。アルバイトは社会への適応・順応という意味もあるし、規律を守る役割もある。小学校の習い事と同様の側面もあると思うが、どうして逆の要因になっているんだろう?</p></li>
</ul>
<h2 id="まとめ">まとめ</h2>
<p>オススメです。良い本でした。<br />
この記事では中学高校の話を多く取り上げたが、本書は中学高校の話だけではない。
幼児教育・小学校・中学校・高校と、生まれてから高校までの年代別に章を分けて、徹底的な分析をしています。
データを用いて分析するのが好きな人、教育や格差の話が気になる人は是非読みましょう。</p>
<p>それでは。</p>
<p><a href="https://www.amazon.co.jp/%E6%95%99%E8%82%B2%E6%A0%BC%E5%B7%AE-%E3%81%A1%E3%81%8F%E3%81%BE%E6%96%B0%E6%9B%B8-%E6%9D%BE%E5%B2%A1-%E4%BA%AE%E4%BA%8C/dp/4480072373/ref=as_li_ss_il?_encoding=UTF8&qid=&sr=&linkCode=li3&tag=limk-22&linkId=078f7d81fa46ad496a88a71f609374b2&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4480072373&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=limk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=limk-22&language=ja_JP&l=li3&o=9&a=4480072373" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
<a href="https://www.amazon.co.jp/%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E4%BA%BA%E7%94%9F%E3%81%AE%E7%A7%91%E5%AD%A6-%E4%B8%8A-%E8%AA%95%E7%94%9F%E3%83%BB%E6%88%90%E9%95%B7%E3%83%BB%E5%87%BA%E4%BC%9A%E3%81%84-%E3%83%8F%E3%83%A4%E3%82%AB%E3%83%AF%E6%96%87%E5%BA%ABNF-%E3%83%87%E3%82%A4%E3%83%B4%E3%82%A3%E3%83%83%E3%83%89%E3%83%BB%E3%83%96%E3%83%AB%E3%83%83%E3%82%AF%E3%82%B9/dp/4150504490/ref=as_li_ss_il?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=ZTS4HUZOQ3OR&dchild=1&keywords=%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E4%BA%BA%E7%94%9F%E3%81%AE%E7%A7%91%E5%AD%A6&qid=1595734840&s=books&sprefix=%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E3%81%98%E3%82%93%E3%81%9B%E3%81%84%E3%81%AE,stripbooks,247&sr=1-1&linkCode=li3&tag=limk-22&linkId=c393bfa1ac1b953a4a33c7235b8ace6f&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4150504490&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=limk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=limk-22&language=ja_JP&l=li3&o=9&a=4150504490" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
<p><a href="https://www.amazon.co.jp/%E3%80%8C%E5%AD%A6%E5%8A%9B%E3%80%8D%E3%81%AE%E7%B5%8C%E6%B8%88%E5%AD%A6-%E4%B8%AD%E5%AE%A4-%E7%89%A7%E5%AD%90/dp/4799316850/ref=as_li_ss_il?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=67YFIC6UU0Q3&dchild=1&keywords=%E5%AD%A6%E5%8A%9B%E3%81%AE%E7%B5%8C%E6%B8%88%E5%AD%A6&qid=1595734852&s=books&sprefix=%E5%AD%A6%E5%8A%9B%E3%81%AE%E7%B5%8C%E6%B8%88%E5%AD%A6,stripbooks,256&sr=1-1&linkCode=li3&tag=limk-22&linkId=4b479bdea80201243203c813280f2b48&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4799316850&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=limk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=limk-22&language=ja_JP&l=li3&o=9&a=4799316850" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
<a href="https://www.amazon.co.jp/%E3%82%8F%E3%82%8C%E3%82%89%E3%81%AE%E5%AD%90%E3%81%A9%E3%82%82-%E7%B1%B3%E5%9B%BD%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E6%A9%9F%E4%BC%9A%E6%A0%BC%E5%B7%AE%E3%81%AE%E6%8B%A1%E5%A4%A7-%E3%83%AD%E3%83%90%E3%83%BC%E3%83%88%E3%83%BBD%E3%83%BB%E3%83%91%E3%83%83%E3%83%88%E3%83%8A%E3%83%A0/dp/4422360019/ref=as_li_ss_il?_encoding=UTF8&qid=1595734918&sr=1-1&linkCode=li3&tag=limk-22&linkId=52b543639b65e2bb0ece3f78cd22b56a&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4422360019&Format=_SL250_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=limk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=limk-22&language=ja_JP&l=li3&o=9&a=4422360019" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
<div class="footnote">
<p class="footnote"><a href="#fn-3bc8abca" name="f-3bc8abca" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">これは「進学期待」であって、実際に進学したかどうかでは無い。本当はそれが一番確実な結果ではないかと思うけど、おそらくデータの制約から不可能だったと推察される。大学に行ったか、浪人→大学のルートも考えれば、高校生の集団を数年間追跡調査しなければいけないから。</span></p>
<p class="footnote"><a href="#fn-bfd015fe" name="f-bfd015fe" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">すみませんこれを立証するデータはありません……個人的な感覚論です……</span></p>
</div>
soratokimitonoaidani
新型コロナウイルスの感染拡大下の2020年4〜6月の生活の感想
hatenablog://entry/26006613600674430
2020-07-19T13:04:17+09:00
2020-08-23T16:19:58+09:00 新型コロナウイルスの感染拡大下の2020年4〜6月の生活の感想 新型コロナウイルスが流行しだしてからの生活や感想をメモ。 こんな経験は二度と無いと思うので。というか二度と起きないでくれよ。 注意 あんまり人に見せることを意識した文章になってないです。自分用のメモという側面が強いです。 予定変更 心理的負担 リモートワーク 増えた時間に何をやってるか? 時間が経つのが早すぎる話 ディスプレイと「何か現状で我慢してしまう」話 予定変更 何月何日と日付が決まっている形の予定が変更・キャンセルになったのは、以下3つ。 高校の部活の友人の結婚式が6月→来年5月に延期になった。 大学のサークルの後輩の結婚…
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a>の感染拡大下の2020年4〜6月の生活の感想</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a>が流行しだしてからの生活や感想をメモ。
こんな経験は二度と無いと思うので。というか二度と起きないでくれよ。</p>
<p><strong>注意</strong> あんまり人に見せることを意識した文章になってないです。自分用のメモという側面が強いです。</p>
<ul class="table-of-contents">
<li><a href="#予定変更">予定変更</a></li>
<li><a href="#心理的負担">心理的負担</a></li>
<li><a href="#リモートワーク">リモートワーク</a></li>
<li><a href="#増えた時間に何をやってるか">増えた時間に何をやってるか?</a></li>
<li><a href="#時間が経つのが早すぎる話">時間が経つのが早すぎる話</a></li>
<li><a href="#ディスプレイと何か現状で我慢してしまう話">ディスプレイと「何か現状で我慢してしまう」話</a></li>
</ul>
<h2 id="予定変更">予定変更</h2>
<p>何月何日と日付が決まっている形の予定が変更・キャンセルになったのは、以下3つ。</p>
<ul>
<li>高校の部活の友人の結婚式が6月→来年5月に延期になった。</li>
<li>大学のサークルの後輩の結婚式2次会が3月→7月に延期→中止になった。</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D4%A5%CE">ピノ</a>キオピーのライブ「AKEBONO」が4月→一旦延期→見通し立たず中止になった。</li>
</ul>
<p>全日本トレイルは3月8日だったので、まぁ何とかギリギリ実施できたなと思う。もう少し遅かったらイベント自粛要請に巻き込まれて開催できなかっただろう。
先行きに対する不安を大いに感じてしまい競技に集中できなかったせいか、すげぇ悪い成績に終わった。俺ってそんなにメンタル弱かったっけ?</p>
<h2 id="心理的負担"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B4%CD%FD%C5%AA">心理的</a>負担</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B4%CD%FD%C5%AA">心理的</a>にはきっつい。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">コロナウイルス</a>の感染が拡大したことそのものは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B4%CD%FD%C5%AA">心理的</a>にそれほど辛いものではない。<br />
それよりもむしろ、労働は従前と変わらない作業量をこなさなければいけないのに、楽しいことが全部吹っ飛んだ。楽しいイベントの当てもなく、日々の労働だけを黙々と進めねばならないのは陰鬱なことである。<br />
俺はだいぶインドア派で、人との関わりも少ないので、行動に対する制約は比較的少ないと思うが、それでもだいぶきっつい。アウトドア派の友達たくさんの人の苦しみはいかばかりだろうか。</p>
<h2 id="リモートワーク">リモートワーク</h2>
<p>リモートで働き出したのはいつからだっただろうか。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Mapのタイムラインで確認してみると、だいたい以下の通りである。</p>
<ul>
<li>2月:25日頃から自宅作業をし始める。ただ顧客打ち合わせの前日当日は出勤。打ち合わせは顧客先まで行く。</li>
<li>3月:顧客打ち合わせの前日と当日は出勤(週1で打ち合わせだったので週2程度出勤)顧客打ち合わせもWeb会議になった。</li>
<li>4月:本格的にリモートワークの指示が出る。4月2日に出勤したのを最後に自宅作業となる。2日は「どうせ書店もしばらく閉鎖するだろうし、本も買えなくなる」と思い、帰りに大型書店に寄って本を買った。プロジェクトが終了して別のプロジェクトに参画するが、最初から完全にリモートのみで説明・進行した。</li>
<li>5月:全てリモートワーク。</li>
<li>6月:学会発表(オンライン)の日だけ「自宅からだと余りに普段通りすぎるので、せめて出勤するか」という謎の理由で出勤した(別に出勤は義務ではない)。他はすべてリモートワーク。</li>
</ul>
<p>4月初旬に会社に行って、次に行ったのは6月10日であった。4〜6月の間で会社に出勤したのはその2回だけだった。<br />
通勤定期も解約した。(払い戻しをするときに、「電車に乗っていなくても<a class="keyword" href="http://d.hatena.ne.jp/keyword/Suica">Suica</a>の残高を使ったらそこが払い戻しの基準の日付になる」という張り紙がしてあった。コンビニなどで少額の買い物をする際はいつも<a class="keyword" href="http://d.hatena.ne.jp/keyword/Suica">Suica</a>なので、「最近を起点に払い戻しだから払い戻し金額が減るのか。JRは酷いや」と思った。だが実際には、緊急事態宣言が出た4月7日が基準日で計算された。疑問に思って「え、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Suica">Suica</a>を使ったらその日付が基準じゃないんですか」と聞いたら、「電車に乗った最後が4月2日だと確認が取れましたので」という返事だった。何でだろ?)</p>
<p>前職だと、リモートワークに向けた動きがもっと遅かっただろうと思われる。(企業文化の点と、ハード寄りなので実際に行かないと仕事にならないという点で。)3月中旬に前職の同期と食事に行ったら、そのときはみんな出勤してるようだったしなぁ。そう考えると迅速に対応した現職で良かったという気持ちになった。</p>
<p>家→会社最寄り駅はかなり混む路線だし、通勤時間が少し長い。満員電車に揺られて会社についたときはもうクタクタ、みたいなのはあった。それが無くなるのはかなり体力的に楽である。</p>
<p>まぁでも、リモートワークバンザイ、サイコー、と手放しで賞賛できるかというと、あんまりできない。以下の問題があるからだ。</p>
<ul>
<li>仕事と私生活との区切り・メリハリがつかない。いつまでも休憩したり、夜遅くまで仕事したりする</li>
<li>ディスプレイがない(まだ買ってないのかよ:後述。)</li>
</ul>
<h2 id="増えた時間に何をやってるか">増えた時間に何をやってるか?</h2>
<p>通勤がなくなったから平日に時間ができた。(休日も予定が無くなったから暇が増えた)その時間にやっているのは以下である。</p>
<ul>
<li>少しの家事、夕食の手伝い、犬の散歩</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%D6%A5%E9SP">スマブラSP</a>(3月15日に「なんとなく」でネット対戦を始めたらすっかりハマってしまい、対戦回数は2000回ほどになった。依然として逆VIP……)</li>
<li>某百科事典の編集</li>
<li>庭の木の枝を切る</li>
<li>ランニング(休日。体重が増えてきたので運動しなければと思って)</li>
</ul>
<h2 id="時間が経つのが早すぎる話">時間が経つのが早すぎる話</h2>
<p>こう振り返ってみると、自宅で働き始めたのが2月下旬だから、約5ヶ月が経過したことになる。月日が経つのは早い。
……月日が経つのは早い、といえば、コロナが起きてから月日が経つのが急激に早くなったような気がする。
なぜだろうか。</p>
<p>時間感覚の話だから正解というものは無いが、いくつか記事を見てみると理由が分かる気がする。</p>
<p><a href="https://r25.jp/article/561114081475273212">土日の体感時間を“1週間”に延ばせる!? 目からウロコの「時間の長さコントロール法」|新R25 - シゴトも人生も、もっと楽しもう。</a></p>
<blockquote><p>狭くて暗い空間は時間が早く過ぎると考えられています。
→だいたい自室(一軒家の子供部屋。6畳くらい?)にいるんだから狭い空間にいる。時間が早く過ぎる。</p>
<p>大人になると時間があっという間に過ぎてしまうのは、私たちが複数の出来事を「まとまった1つの時間」、として捉えてしまっているからなんです。
それは、毎日がルー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%A3%A1%BC">ティー</a>ン化し、出来事の細かい部分を追わなくなるから。
→新しいことをする余地に乏しいし、実際新しいことをしていない。だいたい平日の行為が「仕事して飯を食った」に縮約され、「まとまった1つの時間」になってしまう。</p></blockquote>
<p><a href="https://www.lifehacker.jp/2013/07/130714your_days_feel_longer.html">最近時間が経つのが早い、と感じたらチェックしたい5つのこと | ライフハッカー[日本版]</a></p>
<p>に書いてある、「時の流れを遅くするための5ヶ条」はこれだ。</p>
<ol>
<li>学び続ける:まぁこれは今だからやりやすいね。</li>
<li>新しい場所を訪ねる:厳しい</li>
<li>新しい人に会う:厳しい</li>
<li>新しいことを始めてみる:内容による。「トランポリンの上で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%C3%A5%B8%A5%DC%A1%BC%A5%EB">ドッジボール</a>する/スカイダイビングする」という例が書いてあるし、アウトドアな活動なら厳しい。</li>
<li>自発的になる:外的な環境に著しく制約を受けている状況なのですが。</li>
</ol>
<p>早く感じるのもなるほど納得だわ。</p>
<p>(2020年8月23日追記:同様の話題でまた別の記事が出ていたのでメモ。<br />
<a href="https://www.businessinsider.jp/post-218789">「今年、時間の流れ早すぎない?」コロナ禍で変わる時間感覚。「時」の専門家に聞く | Business Insider Japan</a>)</p>
<h2 id="ディスプレイと何か現状で我慢してしまう話">ディスプレイと「何か現状で我慢してしまう」話</h2>
<p>どう考えても、このリモートワーク生活はこれからもしばらくは続くだろう。<br />
第一に、会社が「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">コロナウイルス</a>問題が解決したのでみんな出勤していいよ!」と言ってくる状況はすぐには起きないだろう。
7月に入って感染が再拡大してきたし。ワクチンができる見通しも立っていないし。<br />
第二に、会社が「リモートワークはもう終わり!禁止!みんな出勤しなさい!」という言ってくる状況はすぐには起きないだろう。
会社によっては「リモートワークはやめます」という変な判断をしてしまうこともあるようだ。</p>
<blockquote><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%B7%BF%A5%B3%A5%ED%A5%CA%A5%A6%A5%A4%A5%EB%A5%B9">新型コロナウイルス</a>の感染拡大をきっかけにテレワークの導入について尋ねたところ現在、実施している企業は31%で、一度も実施していない企業は42%でした。一方で、感染拡大で一時、実施したが、すでにやめた企業が26%にのぼりました。<br />
<a href="https://www3.nhk.or.jp/news/html/20200715/k10012516141000.html">https://www3.nhk.or.jp/news/html/20200715/k10012516141000.html</a></p></blockquote>
<p>だが幸いにして、俺の会社はちゃんとこの状況を分かっているので、今すぐリモートワークをやめるということは無い。</p>
<p>以上の2つの点より、自宅での労働はこれからも続く。
したがって、自宅での労働環境、いや労働に限らず自宅での生活環境をなるべく良いものにするのは
重要で合理的なことだ。</p>
<p>なのに、ああ、それなのに、まだディスプレイを買っていない。<br />
気づいたらもう7月になってるじゃないか。</p>
<p>あ、6月最初に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EB%A5%D4%A5%B7%A5%A2">ルピシア</a>に行って紅茶と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A1%BC%A5%D6%A5%C6%A5%A3%A1%BC">ハーブティー</a>を買ったわ。あと良いお菓子を買いました。
自宅にこもるならせめて美味しいものを食べたいので。<br />
いや、でも、自宅の労働環境を改善するとなったらそこじゃねぇだろ。まずディスプレイを買えよ俺。</p>
<p>「効率は悪いけど、目的を達成できなくはない状態の場合、
そこで金を使わずに(つまり物を買わずに)我慢しがち」という悪い癖が出ている。<br />
<a href="http://coconutsfine.hatenablog.com/entry/20130605/1370442223">ものを買うのは面倒臭がらない方が良い</a>という記事が私は好きで、いま久しぶりに読み返している。今の俺は面倒臭がり過ぎなのかな。</p>
<p>それでは。</p>
soratokimitonoaidani
pandasで ValueError: cannot reindex from a duplicate axisのエラー
hatenablog://entry/26006613580851618
2020-06-08T23:32:03+09:00
2020-09-15T21:17:30+09:00 ValueError: cannot reindex from a duplicate axis というエラーが、pandasにある。 エラーについて色々調べた結果、分からなかったこともあるけど、だいたい以下のとおりだろうか。 行もしくは列の名前に重複がある場合に、特定の操作で発生するようだ? 「複数の行/列のうちどれを使えばよいか分かりませんでした」というような意味かな? pandasのバグを踏んでいる可能性もあるようだ? 最初の質問はエラー再現コードがない…… reindexでエラー発生 普通の使い方 indexに重複があるとエラーが発生する joinでエラー発生……しなかった 普通のjo…
<p><code>ValueError: cannot reindex from a duplicate axis</code></p>
<p>というエラーが、pandasにある。
エラーについて色々調べた結果、分からなかったこともあるけど、だいたい以下のとおりだろうか。</p>
<ul>
<li>行もしくは列の名前に重複がある場合に、特定の操作で発生するようだ?</li>
<li>「複数の行/列のうちどれを使えばよいか分かりませんでした」というような意味かな?</li>
<li>pandasのバグを踏んでいる可能性もあるようだ?</li>
</ul>
<ul class="table-of-contents">
<li><a href="#最初の質問はエラー再現コードがない">最初の質問はエラー再現コードがない……</a></li>
<li><a href="#reindexでエラー発生">reindexでエラー発生</a><ul>
<li><a href="#普通の使い方">普通の使い方</a></li>
<li><a href="#indexに重複があるとエラーが発生する">indexに重複があるとエラーが発生する</a></li>
</ul>
</li>
<li><a href="#joinでエラー発生しなかった">joinでエラー発生……しなかった</a><ul>
<li><a href="#普通のjoin">普通のjoin</a></li>
<li><a href="#indexが重複したDataFrameをjoinエラーにならない">indexが重複したDataFrameをjoin→エラーにならない……</a></li>
</ul>
</li>
<li><a href="#新しい行列の割当てassignでエラー発生">新しい行/列の割当て(assign)でエラー発生</a></li>
<li><a href="#その他">その他?</a></li>
<li><a href="#参考資料">参考資料</a></li>
</ul>
<h2 id="最初の質問はエラー再現コードがない">最初の質問はエラー再現コードがない……</h2>
<p>このエラーに関係するStack Overflowの質問のうち、一番閲覧数が多いのはこれだ。</p>
<p><a href="https://stackoverflow.com/questions/27236275/what-does-valueerror-cannot-reindex-from-a-duplicate-axis-mean">https://stackoverflow.com/questions/27236275/what-does-valueerror-cannot-reindex-from-a-duplicate-axis-mean</a></p>
<p>……しかし、この質問にはエラーを再現させるコードが付属していない。
質問を投稿した人がエラーを出す短いコードを作ろうとしたが、うまく作れなかった、と書いてある。<br />
俺自身も、質問者が書いたコードをちょっと変えてエラーを発生させてみようとしたけど、どうもうまく行かなかった。うーん。</p>
<p>(最初の質問が書かれたのが2014年なので、そこからpandasの仕様が変わってエラーが発生しなくなった、という可能性はある。)</p>
<p>ただ、解答者が名推理をして、「たぶん列名に重複があるんじゃないかな?」と書いたらそれが正解だったらしく、疑問は解決している。</p>
<h2 id="reindexでエラー発生">reindexでエラー発生</h2>
<p>pandasの公式ドキュメントの中で、<code>ValueError: cannot reindex from a duplicate axis</code>の記述がある部分は1箇所だけある。それはreindex関数の説明の中だ。</p>
<p><a href="https://pandas.pydata.org/docs/user_guide/indexing.html?highlight=valueerror#reindexing">https://pandas.pydata.org/docs/user_guide/indexing.html?highlight=valueerror#reindexing</a></p>
<p>以下は、上記の公式ドキュメントと同じ内容である。</p>
<h3 id="普通の使い方">普通の使い方</h3>
<p>まず、reindex()関数の普通の使い方を見てみよう。</p>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd
<span class="synPreProc">import</span> numpy <span class="synStatement">as</span> np
pd.options.display.notebook_repr_html = <span class="synIdentifier">False</span> <span class="synComment"># jupyter notebook上での出力形式を制御するために書いています。無くても動きます。</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 動作環境の確認</span>
<span class="synIdentifier">print</span>(pd.__version__)
<span class="synIdentifier">print</span>(np.__version__)
<span class="synComment"># --------------------</span>
<span class="synConstant">1.0</span>.<span class="synConstant">1</span>
<span class="synConstant">1.18</span>.<span class="synConstant">1</span>
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>s = pd.Series([<span class="synConstant">1</span>, <span class="synConstant">2</span>, <span class="synConstant">3</span>])
s
<span class="synComment"># --------------------</span>
<span class="synConstant">0</span> <span class="synConstant">1</span>
<span class="synConstant">1</span> <span class="synConstant">2</span>
<span class="synConstant">2</span> <span class="synConstant">3</span>
dtype: int64
</pre>
<p>indexを指定して、元のオブジェクトの一部を選択・抽出できる。
もともとのSeriesに無いindex(ここでは3)を指定しても実行できるのが特徴である(該当する行にはNaNが入る)。</p>
<pre class="code lang-python" data-lang="python" data-unlink>s.reindex([<span class="synConstant">1</span>, <span class="synConstant">2</span>, <span class="synConstant">3</span>])
<span class="synComment"># --------------------</span>
<span class="synConstant">1</span> <span class="synConstant">2.0</span>
<span class="synConstant">2</span> <span class="synConstant">3.0</span>
<span class="synConstant">3</span> NaN
dtype: float64
</pre>
<h3 id="indexに重複があるとエラーが発生する">indexに重複があるとエラーが発生する</h3>
<p>ここで、元のオブジェクトのindexに重複したものがあると、エラー<code>ValueError: cannot reindex from a duplicate axis</code>が発生する。以下の通りだ。</p>
<pre class="code lang-python" data-lang="python" data-unlink>s = pd.Series(np.arange(<span class="synConstant">4</span>), index=[<span class="synConstant">'a'</span>, <span class="synConstant">'a'</span>, <span class="synConstant">'b'</span>, <span class="synConstant">'c'</span>])
s
<span class="synComment"># --------------------</span>
a <span class="synConstant">0</span>
a <span class="synConstant">1</span>
b <span class="synConstant">2</span>
c <span class="synConstant">3</span>
dtype: int64
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>labels = [<span class="synConstant">'c'</span>, <span class="synConstant">'d'</span>]
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>s.reindex(labels)
<span class="synComment"># --------------------</span>
---------------------------------------------------------------------------
<span class="synType">ValueError</span> Traceback (most recent call last)
<ipython-<span class="synIdentifier">input</span>-<span class="synConstant">7</span>-5ba024c16ecb> <span class="synStatement">in</span> <module>
----> <span class="synConstant">1</span> s.reindex(labels)
/usr/local/lib/python3.<span class="synConstant">7</span>/site-packages/pandas/core/series.py <span class="synStatement">in</span> reindex(self, index, **kwargs)
<span class="synConstant">4028</span> <span class="synPreProc">@</span><span class="synIdentifier">Appender</span>(generic.NDFrame.reindex.__doc__)
<span class="synConstant">4029</span> <span class="synStatement">def</span> <span class="synIdentifier">reindex</span>(self, index=<span class="synIdentifier">None</span>, **kwargs):
-> <span class="synConstant">4030</span> <span class="synStatement">return</span> <span class="synIdentifier">super</span>().reindex(index=index, **kwargs)
<span class="synConstant">4031</span>
<span class="synConstant">4032</span> <span class="synStatement">def</span> <span class="synIdentifier">drop</span>(
/usr/local/lib/python3.<span class="synConstant">7</span>/site-packages/pandas/core/generic.py <span class="synStatement">in</span> reindex(self, *args, **kwargs)
<span class="synConstant">4542</span> <span class="synComment"># perform the reindex on the axes</span>
<span class="synConstant">4543</span> <span class="synStatement">return</span> self._reindex_axes(
-> <span class="synConstant">4544</span> axes, level, limit, tolerance, method, fill_value, copy
<span class="synConstant">4545</span> ).__finalize__(self)
<span class="synConstant">4546</span>
/usr/local/lib/python3.<span class="synConstant">7</span>/site-packages/pandas/core/generic.py <span class="synStatement">in</span> _reindex_axes(self, axes, level, limit, tolerance, method, fill_value, copy)
<span class="synConstant">4565</span> fill_value=fill_value,
<span class="synConstant">4566</span> copy=copy,
-> <span class="synConstant">4567</span> allow_dups=<span class="synIdentifier">False</span>,
<span class="synConstant">4568</span> )
<span class="synConstant">4569</span>
/usr/local/lib/python3.<span class="synConstant">7</span>/site-packages/pandas/core/generic.py <span class="synStatement">in</span> _reindex_with_indexers(self, reindexers, fill_value, copy, allow_dups)
<span class="synConstant">4611</span> fill_value=fill_value,
<span class="synConstant">4612</span> allow_dups=allow_dups,
-> <span class="synConstant">4613</span> copy=copy,
<span class="synConstant">4614</span> )
<span class="synConstant">4615</span>
/usr/local/lib/python3.<span class="synConstant">7</span>/site-packages/pandas/core/internals/managers.py <span class="synStatement">in</span> reindex_indexer(self, new_axis, indexer, axis, fill_value, allow_dups, copy)
<span class="synConstant">1249</span> <span class="synComment"># some axes don't allow reindexing with dups</span>
<span class="synConstant">1250</span> <span class="synStatement">if</span> <span class="synStatement">not</span> allow_dups:
-> <span class="synConstant">1251</span> self.axes[axis]._can_reindex(indexer)
<span class="synConstant">1252</span>
<span class="synConstant">1253</span> <span class="synStatement">if</span> axis >= self.ndim:
/usr/local/lib/python3.<span class="synConstant">7</span>/site-packages/pandas/core/indexes/base.py <span class="synStatement">in</span> _can_reindex(self, indexer)
<span class="synConstant">3097</span> <span class="synComment"># trying to reindex on an axis with duplicates</span>
<span class="synConstant">3098</span> <span class="synStatement">if</span> <span class="synStatement">not</span> self.is_unique <span class="synStatement">and</span> <span class="synIdentifier">len</span>(indexer):
-> <span class="synConstant">3099</span> <span class="synStatement">raise</span> <span class="synType">ValueError</span>(<span class="synConstant">"cannot reindex from a duplicate axis"</span>)
<span class="synConstant">3100</span>
<span class="synConstant">3101</span> <span class="synStatement">def</span> <span class="synIdentifier">reindex</span>(self, target, method=<span class="synIdentifier">None</span>, level=<span class="synIdentifier">None</span>, limit=<span class="synIdentifier">None</span>, tolerance=<span class="synIdentifier">None</span>):
<span class="synType">ValueError</span>: cannot reindex <span class="synPreProc">from</span> a duplicate axis
</pre>
<p>labelには重複したindexである<code>'a'</code>が含まれていないが、それでもエラーになっているんだな。</p>
<p>「indexが'a'の箇所が複数あるので、どの'a'を使ったら良いかわからないよ!」というくらいの意味だろうか。</p>
<h2 id="joinでエラー発生しなかった">joinでエラー発生……しなかった</h2>
<p>以降の話はpandasの公式ドキュメントに書いていない。書いていないけど、reindex()関数以外でも
<code>ValueError: cannot reindex from a duplicate axis</code>が発生するケースはいくつかあるようだ。</p>
<p><a href="https://stackoverflow.com/questions/27236275/what-does-valueerror-cannot-reindex-from-a-duplicate-axis-mean">https://stackoverflow.com/questions/27236275/what-does-valueerror-cannot-reindex-from-a-duplicate-axis-mean</a></p>
<p>を見ると、データフレームのjoinでエラーが発生すると書いてあった。</p>
<p><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.join.html">https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.join.html</a></p>
<p>ちょっと手元で色々試してみたけど、結果的にはjoinでこのエラーを発生させることはできなかった。</p>
<h3 id="普通のjoin">普通のjoin</h3>
<p>pandasのコミッターであるsinhrksさんの記事がとても秀逸なので、サンプルコードをお借りいたします。
DataFrameを連結・結合する処理で困ったらここを見ましょう。<br />
<a href="http://sinhrks.hatenablog.com/entry/2015/01/28/073327">http://sinhrks.hatenablog.com/entry/2015/01/28/073327</a></p>
<pre class="code lang-python" data-lang="python" data-unlink>left = pd.DataFrame({<span class="synConstant">'A'</span>: [<span class="synConstant">'A0'</span>, <span class="synConstant">'A1'</span>, <span class="synConstant">'A2'</span>],
<span class="synConstant">'B'</span>: [<span class="synConstant">'B0'</span>, <span class="synConstant">'B1'</span>, <span class="synConstant">'B2'</span>]},
index=[<span class="synConstant">'K0'</span>, <span class="synConstant">'K1'</span>, <span class="synConstant">'K2'</span>])
left
<span class="synComment"># --------------------</span>
A B
K0 A0 B0
K1 A1 B1
K2 A2 B2
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>right = pd.DataFrame({<span class="synConstant">'C'</span>: [<span class="synConstant">'C0'</span>, <span class="synConstant">'C2'</span>, <span class="synConstant">'C3'</span>],
<span class="synConstant">'D'</span>: [<span class="synConstant">'D0'</span>, <span class="synConstant">'D2'</span>, <span class="synConstant">'D3'</span>]},
index=[<span class="synConstant">'K0'</span>, <span class="synConstant">'K2'</span>, <span class="synConstant">'K3'</span>])
right
<span class="synComment"># --------------------</span>
C D
K0 C0 D0
K2 C2 D2
K3 C3 D3
</pre>
<pre class="code lang-python" data-lang="python" data-unlink>left.join(right)
<span class="synComment"># --------------------</span>
A B C D
K0 A0 B0 C0 D0
K1 A1 B1 NaN NaN
K2 A2 B2 C2 D2
</pre>
<p>joinは(何も指定しなければ)2つのDataFrameのindexに基づいて、データを結合する。</p>
<h3 id="indexが重複したDataFrameをjoinエラーにならない">indexが重複したDataFrameをjoin→エラーにならない……</h3>
<p>問題はここからだ。
rightのindexを重複させます。</p>
<pre class="code lang-python" data-lang="python" data-unlink>right_dup_1 = pd.DataFrame({<span class="synConstant">'C'</span>: [<span class="synConstant">'C0'</span>, <span class="synConstant">'C2'</span>, <span class="synConstant">'C3'</span>],
<span class="synConstant">'D'</span>: [<span class="synConstant">'D0'</span>, <span class="synConstant">'D2'</span>, <span class="synConstant">'D3'</span>]},
index=[<span class="synConstant">'K0'</span>, <span class="synConstant">'K2'</span>, <span class="synConstant">'K2'</span>])
right_dup_1
<span class="synComment"># --------------------</span>
C D
K0 C0 D0
K2 C2 D2
K2 C3 D3
</pre>
<p>これでエラーになるか?</p>
<pre class="code lang-python" data-lang="python" data-unlink>left.join(right_dup_1)
<span class="synComment"># --------------------</span>
A B C D
K0 A0 B0 C0 D0
K1 A1 B1 NaN NaN
K2 A2 B2 C2 D2
K2 A2 B2 C3 D3
</pre>
<p>エラーにはならなかった。
なるほど。rightにはindexが'K2'の行が2つあるから、leftのK2をrightの2行のそれぞれとjoinした結果になるのね。</p>
<p>……その他、以下のような場合を試してみたが、全然エラーにならなかった。</p>
<ul>
<li>leftのindexが重複している</li>
<li>rightのindexが重複している</li>
<li>leftとrightのindexが重複している</li>
<li>複数dtypeのDetaFrameにしてみる</li>
<li>how='inner'を指定してみる</li>
</ul>
<p>うーーん、分からない。
indexが重複したDataFrameを使ってjoinしてみたけど、エラーが再現しなかった。<br />
どこかのアップデートでjoinの仕様が変わったってことかもしれない?</p>
<h2 id="新しい行列の割当てassignでエラー発生">新しい行/列の割当て(assign)でエラー発生</h2>
<p>これはQiitaに説明があったので、そちらを参照してください。
手元のpandas 1.0.1で試してもエラーが再現しました。良かった。(良かったのか?)</p>
<p><a href="https://qiita.com/waterada/items/c239a6d0424537cfcfb9">https://qiita.com/waterada/items/c239a6d0424537cfcfb9</a></p>
<h2 id="その他">その他?</h2>
<p><a href="https://stackoverflow.com/questions/30788061/valueerror-cannot-reindex-from-a-duplicate-axis-using-isin-with-pandas">https://stackoverflow.com/questions/30788061/valueerror-cannot-reindex-from-a-duplicate-axis-using-isin-with-pandas</a></p>
<p>では以下のように書かれている。</p>
<blockquote><p>The error <code>ValueError: cannot reindex from a duplicate axis</code> is one of these very very cryptic pandas errors which simply does not tell you what the error is.<br />
The error is often related to two columns being named the same either before or after (internally in) the operation.</p>
<p>拙訳:<code>ValueError: cannot reindex from a duplicate axis</code> というエラーは、とっっっても分かりにくいpandasのエラーの一つです。何が誤りだったのか全く教えてくれません。<br />
このエラーは大抵の場合、操作の前や後で同じ名前がついた2つの列があるときに発生します。<br />
(訳注:internally inはよく分からなかったので訳を飛ばしました)</p></blockquote>
<p>結構頑張って検索しても、どういうときにエラーが発生するのかいまいちよく分からなかった。<br />
reindex関数を明示的に使わなくても(おそらく内部でreindex関数が走って)エラーが上がることがあるから、
「reindex? なんじゃ、そりゃ」となるかもしれない。</p>
<h2 id="参考資料">参考資料</h2>
<p><a href="https://stackoverflow.com/questions/27236275/what-does-valueerror-cannot-reindex-from-a-duplicate-axis-mean">https://stackoverflow.com/questions/27236275/what-does-valueerror-cannot-reindex-from-a-duplicate-axis-mean</a></p>
<p>pandasのissueでこのエラー文章を含むものも多数報告されているので、それを見てみるのも良いだろう:<br />
<a href="https://github.com/pandas-dev/pandas/issues?q=is%3Aissue+%22cannot+reindex+from+a+duplicate+axis%22">https://github.com/pandas-dev/pandas/issues?q=is%3Aissue+%22cannot+reindex+from+a+duplicate+axis%22</a><br />
Bugというタグが付いているissueも多い。このエラーに出くわしたら、pandasのバグを踏んでしまった可能性もあるようだ。</p>
<p>(ここまで読んだ人へ:もし自分のエラーがここまで書いてきた内容に該当しないようなら、<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>の@<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linus">Linus</a>_MK(筆者)にお知らせください。 必要に応じて加筆修正します。)</p>
<p>それでは。</p>
soratokimitonoaidani