[Work]

Publications

Degree Thesis

  • 安藤大地 (Daichi Ando): 対話型進化論的計算による作曲支援に関する研究(A Study about Application of Interactive Evolutionary Computation in Composition-Aid System) 博士論文 東京大学大学院新領域創成科学研究科.Mar. 2009.
  • Daichi Ando: "Computer Aided Composition using Interactive Evolution" Master's thesis in Art & Technology, IT University of Gothenburg. Report No. 2004-62, ISSN:1651-4769. Sept, 2004.

Journal Papers and Book Chapter (peer-reviewed)

  • 安藤大地: "ジャズサックス演奏家・学習者の即興演奏時における音高の認知とその変容の実例と考察" 日本音楽即興学会論文誌JASMIMジャーナル 第7号 pp.26--46. 2022年2月.
  • 有山大地, 安藤大地, 串山久美子: "ソフトウェアエフェクタを利用した同一機材を必要としない機械学習によるエレキギター音色の自動再現手法の検討" 情報処理学会論文誌 第61巻 第11号 pp.1729--1740. 2020年11月.
  • Daichi Ando: "Effects of the difference in accented beat between jazz and classical music styles through sight-reading of a jazz ad-lib solo" in New Frontiers in Artificial Intelligence, Springer LNCS Series vol.11717, 2019.
  • 安藤大地,伊庭斉志: "音楽創作支援IECのための買い物フロー型インタフェース" 進化計算学会論文誌.第3巻 第3号 pp.73--84. 2012年12月.
  • 安藤大地: "クラブ系ループ音楽パフォーマンスのためのリアルタイムに音楽をBreedingするシステム" 情報処理学会論文誌 第53巻 第3号 pp.1030--1040. 2012年3月.
  • Daichi Ando, Palle Dahlstedt,Mats G. Nordahl and Hitoshi Iba: "Interactive GP with Tree Representation of Classical Music Pieces" in Giacobini et al. Eds: Application of Evolutionary Computing, Springer LNCS Series vol.4448, pp.577--584. Apr. 2007.
  • 安藤大地, Palle Dahlstedt, Mats Nordahl,伊庭斉志: "対話型GPを用いたクラシック音楽のための作曲支援システム" 芸術科学会論文誌 第4巻 第2号 pp.77--86. 2005年6月.

Musical / Media Art works performed Internationaly (peer-reviewed and invited)

  • Mamoru Takano, Daichi Ando, Tetsuaki Baba, Kumiko Kushiyama: "direction", International Computer Music Conference(ICMC) 2020, 2021, Santiago, Chile.
  • Daichi Ando: "Whitehearted for tenor saxophone and computer", International Computer Music Conference(ICMC) / New York City Electroacoustic Music Festival(NYCEMF) Joint Conference 2019, 2019, NewYork, U.S.A.
  • Daichi Ando: "Softstep for baritone saxophone, electric guitar and computer", International Computer Music Conference(ICMC) 2015, Denton, Texas, U.S.A.
  • Daichi Ando: "Opaline for tenor-saxophone and computer", Asia Computer Music Project(ACMP) 2012, Hsinchu, Taiwan.
  • Daichi Ando: "Towards to Black Plume: an improvisation work for a live interactive breeding system and a saxophonist", Asia Computer Music Project(ACMP) 2011, Tokyo, Japan.
  • Daichi Ando: "Animated Flourish for soprano-saxophone and computer", International Computer Music Conference(ICMC) 2011, Huddersfield, U.K.
  • Daichi Ando: "Rusty Bucket for alto-saxophone and computer", International Computer Music Conference(ICMC) 2007, Copenhagen, Denmark.
  • Daichi Ando: "Wandering Finger for Tape", Music Japan Today 2007, University in Maryland, UMBC.

International Conference (peer-reviewed and others)

  • Daichi Ariyama, Daichi Ando, Kumiko Kushiyama: "The Incidental Music Effector for Picture Books", NICOGRAPH International 2021, P1, Aug. 2021.
  • Hisashi Hatakeyama, Tomoki Toda, Daichi Ando, Shoji Kajita: "Practical Use of LMS and related tools - Case of Japanese University", Open Apereo 2021, Jun. 2021.
  • Mamoru Takano, Daichi Ando, Kumiko Kushiyama: "Sonification method for manipulation of sound information and extending body sensation using spatial sound", International Symposium on Universal Acoustical Communication 2018 (UAC2018), October, 2018, Sendai, Japan.
  • Daichi Ando: "A Research about Rhythm and Phrase Recgnition of Classical Music Performer Leraning Jazz Ad-lib Solo Phrases based on Score", JSAI-isAI International Workshop 2018, Sep. 2018, Yokohama, Japan.
  • Daichi Ando: "Efficiency of adopting Interactive Machine Learning into Electro-Acoustic Composition", Electro-Acoustic Music Stdies 2017, Nagooya, Japan.
  • Daichi Ando: "Real-time breeding composition system by means of genetic programming and breeding procedure", Interanational Computer Music Conference (ICMC) - Sound And Music Computing (SMC) 2014 Joint Conference, Sep. 2014, Athene, Greece.
  • Daichi Ando: "CACIE SB : Genetic Programming based Composition-Aid System by Shopping Basket Interface", International Computer Music Conference (ICMC) 2011 Aug. 2011, Huddersfield, U.K.
  • Daichi Ando: "Improving User-Interface of Interactive EC for Composition-Aid by means of Shopping Basket Procedure",New Interface for Musical Expresssion (NIME) 2011 Jul. 2011, Oslo, Norway
  • Daichi Ando, Palle Dahlstedt,Mats G. Nordahl and Hitoshi Iba: "Computer Aided Composition by means of Interactive GP" Proceedings of the International Computer Music Conference 2006, New Orleans, USA. pp:254-257. Oct. 2006.
  • Daichi Ando, Hitoshi Iba: "Real-time Musical Interaction between Musician and Multi-agent System" Proceedings of the 8th International Conference on Generative Art 2005, Milan, Italy. pp:93-100. Dec. 2005.
  • Takayuki Rai, Daichi Ando, Shu Matsuda, Chikashi Miyama: "DIPS for Linux" Resonances International Convention on Technologies for Music 2003, Paris, IRCAM, Oct. 2003.
  • Takayuki Rai, Shu Matsuda, Chikashi Miyama, Daichi Ando: "DIPS for Mac OS X and Linux" Resonaces International Convention on Technologies for Music 2002, Paris, IRCAM, Oct. 2002.
  • Shu MATSUDA, Takayuki RAI, Chikashi Miyama, Daichi ANDO: "DIPS for Linux and Mac OS X" Proceeddings of the International Computer Music Conference 2002, Gothenburg, Sweden. Sep. 2002

講演など

  • 安藤大地: 「音楽大学における人工知能の授業の実践」 第2回日本AI音楽学会フォーラム, 2019年11月.
  • 安藤大地: 「人工知能と音楽の考え方 - 「作曲家」の立場を使って「工学的」に見る」 第1回日本AI音楽学会フォーラム,2018年11月.
  • 安藤大地: 「人間と人工知能が協調したモノづくり - 「家族の好みを反映したレシピを提案するシステム」を例に」第15回ユニテックフーズ技術セミナー.2018年5月.

国内学会・研究会等 (査読有)

  • 新井 里奈,安藤 大地,向井 智彦: "スマートフォン用の店舗利用者行動先読み型ウェブアプリケーション" 情報処理学会インタラクション2019シンポジウム, 3P-86, 2019年3月.
  • 高野 衛,串山 久美子,安藤 大地,須田 拓也,馬場 哲晃: "ポインティング・デバイスの操作感覚に影響を与えることを目的とした音響フィードバック" 情報処理学会インタラクション2019シンポジウム, 3B-47, 2019年3月.
  • 有山 大地,安藤 大地,串山 久美子: "MFCCを距離尺度に用いたGAによるエレキギターの音色再現システムの開発" 情報処理学会インタラクション2019シンポジウム, 2B-31, 2019年3月.
  • 安藤大地: "EWI wind-synthesizerのためのトーキングボックス的ヴォコーダの設計とセンサのアサイン" 情報処理学会インタラクション2019シンポジウム, 2B-23, 2019年3月.
  • 大森 葵,向井 智彦,安藤 大地: "3次元キャラクタモーション制作履歴データ事例に対する一検討" 情報処理学会インタラクション2019シンポジウム, 1P-75, 2019年3月.
  • 宇野花梨,安藤大地,笠原信一: "3DCG技術を用いた2Dアニメーションの制作の効率" 情報処理学会インタラクション2018シンポジウム, 2B44, 2018年3月.
  • 安藤大地: "CPPN表現とNeuro-Evoluationを用いたエレクトロニカのためのノイズ音素材" 情報処理学会インタラクション2018シンポジウム, 1B58, 2018年3月.
  • 高野衛,安藤大地,串山久美子: "運動学習支援を目的とした多変数マッピングを用いた動作情報の可聴化手法" 情報処理学会インタラクション2018シンポジウム, 1B26, 2018年3月.
  • 矢追那実,安藤大地,笠原信一: "「三次元スケッチブック」の可能性" 情報処理学会インタラクション2017シンポジウム, 3-409-71, 2017年3月.
  • 磯野優夏,安藤大地,笠原信一: "シネマグラフを簡易的に作成する新手法の提案" 情報処理学会インタラクション2017シンポジウム, 3-408-78, 2017年3月.
  • 宇野花梨, 安藤大地, 笠原信一: "3DCG技術を活用した2Dアニメーション制作システムの提案" 情報処理学会インタラクション2017シンポジウム, 2-510-09, 2017年3月.
  • 三善優紀,安藤大地,笠原信一: "周辺情報の把握による二輪車向け運転支援システムの開発" 情報処理学会インタラクション2017シンポジウム, 2-410-68, 2017年3月.
  • 安藤大地: "対話型遺伝的プログラミングを用いた無調性音高配列からの和声進行の生成" 情報処理学会インタラクション2017シンポジウム, 2-403-47, 2017年3月.
  • 高野衛,安藤大地,笠原信一: "運動学習支援を目的とした動作情報における可聴化手法の提案" 情報処理学会インタラクション2017シンポジウム, 1-408-7, 2017年3月.
  • 本田 将大,安藤 大地,笠原 信一: "国際化する医療現場における医師と外国人患者とのコミュニケーション支援に関する研究" 情報処理学会インタラクション2016シンポジウム, 2B27, 2016年3月.
  • 安藤 大地: "マルチスピーカシステムのためのパンニングモジュレーションの基礎検討" 情報処理学会インタラクション2016シンポジウム, 1C74,2016年3月.
  • 川島 絵里奈,安藤 大地,笠原 信一: "進化的アルゴリズムを用いた家族向け献立提案システムの試作" 情報処理学会インタラクション2016シンポジウム, 1C53, 2016年3月.
  • 三善 優紀,安藤 大地,笠原 信一: "周辺情報の把握による二輪車向け運転支援システムの開発" 情報処理学会インタラクションシ2016シンポジウム, 1C51, 2016年3月.
  • 有山 大地,安藤 大地,笠原 信一: "進化論的計算を用いたエレキギターの音色再現手法の提案" 情報処理学会インタラクション2016シンポジウム, 1B24, 2016年3月.
  • 松岡 宗人, 安藤 大地, 笠原 信一: "マルチウィンドウにより情報の収集・比較を可能とするWeb検索ツールの提案" 情報処理学会インタラクション2015シンポジウム, B20, 2015年3月.
  • 安藤大地: "ジャズ即興演奏における4ビートベースラインの2段階対話型遺伝的プログラミングによる生成" 情報処理学会インタラクション2015シンポジウム, B18, 2015年3月.
  • 三善 優紀,安藤 大地,笠原 信一: "コンピュータビジョン周辺監視による二輪車向け安全性向上システムの開発のための基礎検討" 情報処理学会インタラクション2015シンポジウム, A61, 2015年3月.
  • 浜田 真成,安藤 大地,笠原 信一: "idea in: プロジェクト管理を効率化するWebアプリケーション その3 - タスクチャート手法によるプロジェクトの目的別可視化" 情報処理学会インタラクション2015シンポジウム, A19, 2015年3月.
  • 有山 大地,安藤 大地,笠原 信一: "位置・時間を主軸においたWebコンテンツのストーリー形式まとめシステム" 情報処理学会インタラクション2015シンポジウム, A17, 2015年3月.
  • 小林 央,安藤 大地,笠原 信一: "VOCALOIDでの話し言葉作成に特化したツールの制作と提案" 情報処理学会インタラクション2014シンポジウム, C3-3, 2014年3月.
  • 染矢 さらら,安藤 大地,笠原 信一: "メロディモーフィング手法を用いた初学者向けの作曲支援システムの研究" 情報処理学会インタラクション2014シンポジウム, B6-2, 2014年3月.
  • 浜田 真成,安藤 大地,笠原 信一: "idea in: プロジェクト管理を効率化するWebアプリケーション その2 - タスクチャート手法の提案", 情報処理学会インタラクション2014シンポジウム, B4-1, 2014年3月.
  • 黒田 宙馬,笠原 信一,安藤 大地: "3Dインターフェースによるプレゼンテーションツールの可能性提案" 情報処理学会インタラクション2014シンポジウム, B4-0, 2014年3月.
  • 安藤 大地: "GPS軌跡と写真から旅行記のBGMを作成して再生するWebシステム",情報処理学会インタラクション2014シンポジウム, B3-6, 2014年3月.
  • 多々良 友理,笠原 信一,安藤 大地: "モザイク画像の認知に関する考察とそれに基づいたグラフィックデザイン支援プログラムの開発" 情報処理学会インタラクション2014シンポジウム, A3-8, 2014年3月.
  • 安藤 大地: "GPを用いたアドリブジャズギターの演奏と主観的演奏表情状態の紐付けに関する検討 ~人間の演奏表情を読み取り反応するジャムセッションシステムの構築に向けて~" 情報処理学会インタラクション2013シンポジウム, 2EXB-37, 2013年3月.
  • 木下 夏織,安藤 大地,笠原 信一: "モールス信号を用いた新しいユーザインタフェースの提案と制作" 情報処理学会インタラクション2013シンポジウム, 1EXB-44, 2013年3月.
  • 浜田 真成,安藤 大地,笠原 信一: "Idea In: プロジェクト管理を効率化するWebアプリケーション 提案と制作" 情報処理学会インタラクション2013シンポジウム, 1EXB-08, 2013年3月.
  • 為廣 愛美,安藤 大地,笠原 信一: "ユーザーフレンドリーな対話型ヘルプキャラクターの制作と提案" 情報処理学会インタラクション2012シンポジウム, 1EXB-35, 2012年3月.
  • 安藤大地: "地図上に投稿された現地写真からBGMをみんなで生成するシステム" 情報処理学会インタラクション2012シンポジウム, 1EXB-17, 2012年3月.
  • 丁 慶松,笠原 信一,安藤 大地: "ARによる「紙のピアノ」の提案" 情報処理学会インタラクション2011シンポジウム, 3CR3-2, 2011年3月.
  • 高 碩,清水 要,笠原 信一,安藤 大地: "裸眼立体視による注視点の動きを利用した視力回復訓練ソフトウェアの開発" 情報処理学会インタラクション2011シンポジウム, 1DEX-3, 2011年3月.
  • 谷澤奈津妃,笠原 信一,安藤 大地: "ゲーム感覚で楽しめるCube型3Dフォトアルバムの構築" 情報処理学会インタラクション2011シンポジウム, 1DEX-1, 2011年3月.
  • 梶家彩実,安藤 大地,笠原 信一: "HEaSシステムによる新しいライフスタイルの提案" 情報処理学会インタラクション2011シンポジウム, 1CR3-17, 2011年3月.
  • 安藤 大地,笠原 信一: "フォトアルバムから音楽を生成するプログラムの対話型GPを用いた最適化" 情報処理学会インタラクション2011シンポジウム,1CR3-12, 2011年3月.
  • 安藤大地,馬場哲晃:"マルチタッチディスプレイを利用した電子擦弦楽器とエフェクトコントローラ" 情報処理学会インタラクション2010シンポジウム,2010年3月.
  • 安藤大地,稲田雅彦,丹治信,伊庭斉志:"IECを用いた作曲支援のためのユーザインタフェース" 情報処理学会,インタラクション2009シンポジウム, 2005年3月.
  • 安藤大地,丹治信,伊庭斉志:"IECを用いた作曲支援システムCACIEのユーザインタフェース改良" 情報処理学会インタラクション2007シンポジウム, 2007年3月.
  • 安藤大地,Palle Dahlstedt,Mats Nordahl,伊庭斉志:"対話型進化論的計算によるクラシック音楽作曲支援システム: CACIE" 情報処理学会インタラクション2005シンポジウム (情報処理学会シンポジウムシリーズ論文集Vol.2005, No.4) pp.185-186, 2005年2月-3月.

国内学会・研究会等 (査読無)

  • 堀内尚,安藤大地,向井智彦「規則的成長と縄張り争いによるサンゴのモデリング手法の提案」情報処理学会第84回全国大会. 7ZG-01. 2022年3月.
  • 胡博文,安藤大地,向井智彦 "Analysis and Synthesis of Eye Movements for Conversational Agent" 情報処理学会第84回全国大会. 4ZF-06. 2022年3月.
  • 栗﨑美博,安藤大地,向井智彦「運動学的知見を考慮した鳥の飛行モデル構築に向けた検討」情報処理学会第84回全国大会. 4ZF-05. 2022年3月.
  • 西奥一樹,安藤大地,向井智彦「アバターの体型とユーザの好みを考慮したシャツ形状デザインシステムの提案」情報処理学会第84回全国大会. 4N-02. 2022年3月.
  • 森中 暖乃, 安藤 大地, 向井 智彦「単語の発音リズムを基準にした譜割生成の研究」先端芸術音楽創作学会会報vol.13, no.1. pp.34--39. 2021年2月.
  • 有山 大地, 安藤大地, 串山 久美子「童話の為の劇伴エフェクターの制作と実践」先端芸術音楽創作学会会報vol.13, no.1. pp.30--33. 2021年2月.
  • 堀内 尚, 向井 智彦, 安藤 大地「サンゴ礁の3DCGモデリング手法の研究」情報処理学会Visual Computing(VC)2020シンポジウム, P49, 2020年12月.
  • 栗﨑 美博, 向井 智彦, 安藤 大地「鳥の生体力学に基づく飛行アニメーション制作法の研究」情報処理学会Visual Computing(VC)2020シンポジウム, P39, 2020年12月.
  • 西奥 一樹, 向井 智彦, 安藤 大地「ユーザの体型を考慮した服飾形状デザインシステムの提案」情報処理学会Visual Computing(VC)2020シンポジウム, P32, 2020年12月.
  • 胡 博文, 向井 智彦, 安藤 大地「仮想人間との対話のための眼球運動の分析および合成」情報処理学会Visual Computing(VC)2020シンポジウム, P19, 2020年12月.
  • 舟木里美,安藤大地,向井智彦「犬の散歩ルート探索のための「回避点」「寄り道地点」を考慮に入れた経由点の決定手法」第82回情報処理学会全国大会.2020年3月.
  • 佐藤晴海,安藤大地,向井智彦「景観情報クイズを用いた大規模地下街での「ジオキャッシング」」第82回情報処理学会全国大会.2020年3月.
  • 西智菜美,安藤大地,向井智彦「ユーザーニーズに合わせた花火鑑賞スポット提案システム」第82回情報処理学会全国大会.2020年3月.
  • 山田あゆみ,安藤大地,向井智彦「エコ・クッキングを促すための食物重量物提示システムにおけるユーザ体験の研究」第82回情報処理学会全国大会.2020年3月.
  • 及部礼成,安藤大地,恩田陽人,林真一郎,向井智彦「インク開発支援のための主成分分析と遺伝的プログラミングによる数理モデルの導出」第82回情報処理学会全国大会.2020年3月.
  • 安藤大地,冨上健太郎,有山大地,土屋真,小貫信比古「e-AMEFUTO: 大学スポーツ支援を目的とした現役選手・引退選手の認知を取り込んだアメフトシミュレータの開発」第17回進化計算学会研究会.2020年2月.
  • 及部礼成,安藤大地,恩田陽人,林真一郎,向井智彦「インク開発支援のための遺伝的プログラミングと局所探索の組み合わせによる数理モデルの導出」,第17回進化計算学会研究会.2020年2月.
  • 安藤 大地, 長嶋, 洋一, 落 晃子, 長山弘: "パネルディスカッション テクノロジーを用いた即興演奏・即興演奏教育の拡張" 日本音楽即興学会第11回学術大会. 2019年12月.
  • 馬場 哲晃, 石曽根 奏子, 高野 衛, 安藤 大地, 渡邉 英徳, 釜江 常好: "視覚障害者の屋外移動時における周辺物体検出の可聴化に関する基礎検討とプロトタイピング", 情報処理学会第10回アクセシビリティ研究会 vol.2019-AAC-10, no.6, pp:1--4. 2019年8月.
  • 安藤大地: "ジャズ単音アドリブソロにおける音高認知の調査" 先端芸術音楽創作学会会報 Vol.11, No.2. pp:16--19. 2019年7月.
  • Yibin Yan, 向井智彦,安藤大地: "フェイシャルアニメーションの非線型制御法の研究" 情報処理学会Visual Computing(VC)2019シンポジウム, 2019年7月.
  • 安藤大地: "2-5-1フレーズ練習記録の一人称研究を例にしたジャズ即興演奏生成システムのための検討" 人工知能学会2019年度全国大会, 3L4-OS-22b-02, 2019年6月.
  • 安藤大地: "クラシック演奏家のジャズ即興演奏習得過程の記録と考察" 日本音楽即興学会第10回学術大会, 2018年12月.
  • 有山大地,安藤大地,串山久美子: "MFCCを距離尺度に用いたエレキギター音色の機械学習手法に関する研究" 先端芸術音楽創作学会会報vol.10, no.3, pp:24--29. 2018年11月.
  • 高野衛,安藤大地,串山久美子: "音響情報の操作と空間音響を用いた身体イメージの変化を目的とした可聴化手法" 第10回多感覚研究会, 2018年10月.
  • 安藤大地: "クラシック音楽演奏家のジャズ音楽のフレーズ認知に関する調査と考察" 人工知能学会第26回身体知研究会,2018年9月.
  • 安藤大地: "クラシック演奏家のジャズ演奏コピーにおけるリズム・フレーズ把握の調査" 先端芸術音楽創作学会会報vol.10, no.2, pp:5--9. 2018年7月.
  • 高野 衛, 安藤 大地, 馬場 哲晃, 串山 久美子: "空間音響による身体イメージの変化を用いたインスタレーション “quad” sonification for hand stroke", 先端芸術音楽創作学会会報vol.10, no.2, pp.1--4. 2018年7月.
  • 安藤大地: "対話型機械学習の実践的な作曲への応用" 先端芸術音楽創作学会会報vol.9, no.2, pp:1--4, 2017年9月.
  • 高野衛,安藤大地,馬場哲晃,串山久美子「動作情報に関する複数の音響パラメータへの多変数マッピングを用いた可聴化手法の考察」先端芸術音楽創作学会会報vol.9, no.1, pp:18--23. 2017年7月.
  • 高野衛,安藤大地,笠原信一「動作情報を用いたパフォーマンス作品による可聴化手法の考察」先端芸術音楽創作学会会報vol.8, no.3, pp:1--4. 2016年12月.
  • 高野衛,安藤大地,笠原信一「動作分析の可聴化における現状の考察とインタラクティブな可聴化システムの検討」先端芸術音楽創作学会会報vol.8, no.1, pp:1--6. 2016年7月.
  • 有山大地,安藤大地,笠原信一: "進化論的計算を用いたエレキギターの音色再現手法の提案" 先端芸術音楽創作学会会報vol.7, no.2, pp:10--14, 2016年3月.
  • 高野衛,安藤大地,笠原信一: "アコースティック・ギターを素材とした音響作品 “orb” for electronics の制作", 先端芸術音楽創作学会会報vol.7, no.2, pp:7--9, 2016年3月.
  • 染矢さらら, 安藤大地, 笠原信一: "GTTMタイムスパン木を用いた旋律モーフィング手法の検討",第102回情報処理学会音楽情報科学研究会, 2014年2月.
  • 吉村 ももこ, 笠原 信一, 安藤 大地: "レイトレーシングにおける半影表現の新しいアプローチ -ライトオブスタクルデプス-",第154回情報処理学会グラフィクスとCAD研究会, 2014年2月.
  • 安藤大地,阿部ちひろ,遠藤秀行,伊藤仁,伊東直哉,三木翔太,森勢将雅,中村友彦,岡田美咲,佐々木将人,澤田真吾,橘秀幸,飛世速光,宇野愛,魚田知美,山田祐雅,山本龍一: "デモンストレーション:音楽情報処理の研究紹介 XI", 情報処理学会音楽情報科学研究会, IPSJ, 2012-MUS-96, No.18, 2012年8月.
  • 安藤大地: "首都大学東京インダストリアルアートコース スタジオ・レポート" 情報処理学会音楽情報科学研究会, IPSJ, 2011-MUS-93, No.3, 2011年12月.
  • 馬場哲晃,有田光希,安藤大地,伊藤悠真,金井隆晴,小池宏幸,村主大輔,辰巳直也,平井重行,平井辰典,深山覚,水本直希,山本龍一: "デモンストレーション:音楽情報処理の研究紹介 X", 情報処理学会音楽情報科学研究会, IPSJ, 2011-MUS-91, Vol.2011-MUS-91 No.16, July. 2011.
  • 中野倫靖,大沼翔,金泰憲,黒沢佳史,斉藤優理,斎藤佳紀,奥村健太,田中駿二,浜中雅俊,帆足啓一郎,森山剛,吉田周平,吉谷幹人,安藤大地: "デモンストレーション:音楽情報処理の研究紹介 IX", 情報処理学会音楽情報科学研究会, IPSJ, 2011-MUS-91, Vol.2010-MUS-86 No.21, 2010年7月.
  • 安藤大地,伊庭斉志: "時系列メディアを生成対象としたアート創作支援IECのインタフェース", 進化計算シンポジウム2009, 1-08. 2009年12月.
  • 安藤大地,梶克彦,北市健太郎,草間かおり,佐藤和哉,竹川佳成,浜中雅俊,深山覚,松原正樹: "デモンストレーション:音楽情報処理の研究紹介 VII", 情報処理学会音楽情報科学研究会, IPSJ, 2009-MUS-81, No.22, 2009年7月.
  • 安藤大地: "動画投稿サイトにおける音源トラックの共有を目的とした投げ銭システムの検討と提案" 情報処理学会音楽情報科学研究会, IPSJ, 2009-MUS-80, No.10, 2009年5月.
  • 渡辺晃生,安藤大地,稲田雅彦,丹治信,伊庭斉志: "IECを用いた歌声パラメータの最適化システム" 情報処理学会音楽情報科学研究会, IPSJ, 2009-MUS-79, No.2, pp:5-10, 2009年2月.
  • 稲田雅彦,安藤大地,丹治信,伊庭斉志: "対話型作曲支援システムにおけるユーザ嗜好の獲得" 情報処理学会エンタテイメントコンピューティング研究会,IPSJ, 2008-EC-11, No.12, 2009年12月.
  • 中野倫靖,福島直,小川圭祐,早渕 功紀,梶原祥平,浜中雅俊,一瀬護,数森康弘,橋本祐輔,石先広海,神田竜,冨林豊,平井重行,渡辺晃生,安藤大地,竹川佳成: "デモンストレーション:音楽情報処理の研究紹介 VI", 情報処理学会音楽情報科学研究会, IPSJ, 2008-MUS-76, No.18, 2008年8月.
  • 丹治信,安藤大地,伊庭斉志: "PCFGの文法拡大による音列パターン解析" 情報処理学会音楽情報科学研究会, IPSJ, 2008-MUS-76, No.13, pp:69-74, 2008年8月.
  • 安藤大地,丹治信,稲田雅彦,伊庭斉志: "初心者向け音楽創作IECのためのユーザアシスト機能についての検討" 情報処理学会音楽情報科学研究会, IPSJ, 2008-MUS-75, pp:123-128, 2008年5月.
  • 稲田雅彦,安藤大地,丹治信: "Sign Do Sound:対話型作曲支援システムの能動的音楽聴取インタフェース--インスタレーションに対するIECインタフェースの取り組み" 映像情報メディア学会技術報告 Vol.32, No.15, pp:25--28, 2008年2月.
  • 安藤大地,伊庭斉志: "音楽CGMのユーザをターゲットとした音楽創作支援システムの開発に向けて" 第1回同人音楽研究会, 2008年2月.
  • 丹治信,安藤大地,伊庭斉志: "確立文脈自由文法による旋律の拍節モデル推定" 情報処理学会音楽情報科学研究会,IPSJ, 2007-MUS-73, Vol.2007, No.127, ISSN:0919-6072, pp:57-62, 2007年12月.
  • 安藤大地,稲田雅彦,丹治信,伊庭斉志: "能動的音楽聴取インタフェースの作曲支援IECへの取り込み" 情報処理学会音楽情報科学研究会,IPSJ, 2007-MUS-73, Vol.2007, No.127, ISSN:0919-6072, pp:1-6, 2007年12月.
  • 安藤大地、伊庭斉志: "木構造型遺伝子を用いたクラシック音楽作曲支援システム:CACIE" 人工知能学会2007年全国大会, 3C7-2, 2007年6月.
  • 丹治信,安藤大地,伊庭斉志: "GPを用いた旋律のグルーピングルール生成" 情報処理学会音楽情報科学研究会,IPSJ, 2006-MUS-68, Vol.2006, No.133, ISSN:0919-6072, pp:67-72, 2006年12月.
  • 安藤大地,丹治信,伊庭斉志: "ECを用いた作曲支援システムと作曲モデルの客観的評価手法" 情報処理学会音楽情報科学研究会,IPSJ, 2006-MUS-68, Vol.2006, No.133, ISSN:0919-6072, pp:29-34, 2006年12月.
  • 安藤大地,伊庭斉志: "人間の演奏者と音楽インタラクションを行うマルチエージェントシステムの構築" 情報処理学会音楽情報科学研究会,IPSJ, 2005-MUS-63, Vol.2005, No.129, ISSN:0919-6072, pp:43-48, 2005年12月.
  • 安藤大地,Palle Dahlstedt,Mats Nordahl,伊庭斉志: "対話型進化論的計算による作曲支援システム: CACIE" 情報処理学会音楽情報科学研究会,IPSJ, 2005-MUS-59, Vol.2005, No.14, ISSN:0919-6072, pp:55-60, 2005年2月.
  • 松田周,安藤大地,美山千香士,酒井由: "マルチメディアビジュアルプログラミング環境DIPS2" 情報処理学会音楽情報科学研究会,IPSJ, 2003-MUS-51 Vol.2003, 2003年8月.
  • 松田周,美山千香士,安藤大地: "マルチメディアプログラミング環境DIPS : Linux とMacOSXへの移植" 情報処理学会音楽情報科学研究会,IPSJ, 2002-MUS-48 Vol.2002, 2002年12月.
  • 橋田光代,松田周,美山千香士,安藤大地: "DIPSプログラミングの実際" 情報処理学会音楽情報科学研究会,IPSJ, 2000-MUS-38 Vol.2000, 2000年12月.
  • 橋田光代,美山千香士,安藤大地: "DIPSエクスターナルオブジェクトの開発と作品創作への応用" 情報処理学会音楽情報科学研究会,IPSJ, 2000-MUS-36, Vol.2000, 2000年8月.

メディア露出など

  • "NHK サイエンスZERO 進化研究最前線〜ダーウィン進化論150年〜" 2008年2月7日放送.
    http://www.nhk.or.jp/zero/contents/dsp236.html

[Work/Class/Python3の基礎とデータ処理/python_basic]

CSVの取得とPlot, pandas.DataFrameの取り扱い

Pandas.DataFrame

read_csv関数とインターネットからの読み込み

pandas.read_csv関数で読み込むと, DataFrameという形式で読み込んでくれる.このDataFrameは2次元の表に「行と列,それぞれにラベルがついている」データ形式であり,さらに複数のデータ型,例えば整数や実数,文字列を,一つの表の中に混在させることができる.(ただしもちろんデータとしてまとまりがなければならないので,行か列のどちらかでデータ型は揃っている必要はある)

また,インターネット上にあるファイルも直接読み込むことができる.この時「文字コード」と呼ばれる「日本語を扱うための形式」を指定する必要がある.

import pandas as pd

dataframe = \ # 改行の時はバックスラッシュ(半角円マーク)を入れると次の行のインデントは無視され,1つの行として扱われる.
  pd.read_csv('http://www.city.hachioji.tokyo.jp/contents/open/002/p005866_d/fil/nenreibetsu_jinkou_2506.csv', \
              encoding='shift-jis')

dataframe.head()

DataFrameオブジェクトのhead関数は,わかりやすく頭の部分だけを出力してくれる.各コードセルの「最後の行」で実行すること.もちろんhead関数の結果を変数に代入し,print関数に入れてやれば,セルのどこでも可能だが,Google Colaboratory上では(セルの最後の行で実行したようには)色分けはされない.

dataframe.head()のGoogle Colaboratoryでの実行結果

ちなみに,Google Colaboratoryではなく,Anaconda等で自分のコンピュータでPythonを実行する時には,URLの部分をファイル名にしてやればよい.(大きいサイズのCSVの時には予めGoogle Colaboratoryにファイルをアップロードしておいて,そのファイル名で読み込むこともできる)

Pythonはインデントでブロックが決まるので,ただ改行しただけではプログラムが実行できなくなってしまう.そこで1行長すぎて改行したい時には,\を入れる.半角バックスラッシュは日本語キーボードでは半角の円マーク相当する.

文字コード

文字コードはencoding='shift-jis'の場所で指定している.通常,官公庁のオープンデータはCSVと呼ばれる「値がカンマで区切られたExcelのシートのような形式」のテキストファイルとして提供されているが,日本語Excelで作られたためか文字コードが「シフトJIS」という形式になっている.

Python3の標準の文字コードは「UTF-8(8bitにエンコードされたUnicode)」という形式であり,現在のWebページのほとんどこのUTF-8という文字コードを採用しているが,何故かExcelのCSV書き出しは文字コードをシフトJISで書き出し続けている.そこで官公庁データを読み込む時には文字コードを基本的にシフトJISだと覚悟して,encoding='shift-jis'をつけた方が良い.

列の値のラベルを使った取り出し

通常CSVは値だけが入っていることは少なく,1行目が「列の各項目の名前」になっていることが多い.この「列の名前」……つまり列のラベルを使った操作をpandas.DataFrame形式のデータでは行うことができる.

numpyは「値だけ」の行列だったのに対して,pandas.DataFrame形式では「列のラベル」(もちろん行のラベルもある)を使って操作できることに最大の特徴がある.

例えば,「その列の値だけ」を「その列のラベルを使って」取り出すことができる

locという関数(正確にはオペレータ)を使うが,
loc[:, '列のラベル']のように取り出す.

最初の:は「行は全部」(0~あるだけ)という意味.
loc[0:, '列のラベル']とも書ける.

dataframe.loc[1:3, '人口_男']と書くと,
'人口_男'列の「1行目から3行目」を抽出する,という意味になる.
(行番号は0から始まることに注意)

# それぞれ「列」に分解していく

# 年齢の「列」だけを,列のラベルを使って,1次元配列で取り出していく
age = dataframe.loc[:, '年齢']
population_man = dataframe.loc[:, '人口_男'] # このデータはアンダースコアが全角であることに注意
population_women = dataframe.loc[:, '人口_女']
population_sum = dataframe.loc[:, '人口_合計']


# データ形式を表示してみる
print(type(population_man)) # DataFrameの1次元版はSeriesと呼ぶ.ほぼnumpyと同じように扱うことができる

# 試しに中身の表示
print(population_man)

type関数に変数を入れることで,変数のデータ形式を確認することができる.ちなみにpandas.DataFrameから列だけを取り出した1次元配列はpandas.Seriesというデータ形式になっている.現在は,ほぼnumpy1次元配列と同じように扱うことができる.

明確にnumpyの1次元配列に変換したい場合,格納しているSeriesの変数名.valuesnumpy配列にアクセスできる.(関数ではないことに注意)

上記では,列にラベルがある場合を想定したが,もちろん行の方にラベルがあっても構わない.また両方とも行or列のインデックス指定(行番号指定,列番号指定)でも取り出せる.(loc[1:3, 4:6]は1行目~3行目かつ4列目~6列目を取り出す,という意味になる)

CSVのデータを基にグラフを描く

X軸とY軸に,取り出した列を与えて,折れ線グラフを描画する.

この場合X軸は年齢,Y軸は男性,女性,合計の年齢に対応する人口である. すでに前のセルで,列のデータを取り出してるので,それぞれの組を与えるだけで良い

# グラフ表示のライブラリmatplotlib.pyplot
import matplotlib.pyplot as plt

# X軸に年齢, Y軸にそれぞれの人数を入れる
# pandas.Seriesでもnumpyと同じように読んでくれる

# labelは凡例で表示される文字列.
# これをつけておかないと,どの色が何のデータを表しているのかわからなくなる.
plt.plot(age, population_man, label='man')
plt.plot(age, population_women, label='woman')
plt.plot(age, population_sum, label='sum')

# 凡例を表示させる
plt.legend()

#グラフを描画する
plt.show()

Google Colaboratoryでのグラフ描画の結果は以下のようになる.

matplotlib.pyplotで描画した結果

各種ライブラリのCSV読み込み機能

先の例ではpandasでCSVファイルを読み込んだが,実は他にも方法がある.しかしpandasのread_csvのようには便利ではないし,一度別のurllib.request.urlopen関数を使ってインターネットから取得する部分を別に書いてやる必要があったり,文字コードの読み込みに難があったりなどするため,現実的ではない.

標準csvライブラリcsv.reader()による読み込み

Python3の標準CSVライブラリは,

  • 標準ライブラリのcodecs.open()関数で,文字コードを指定しつつファイルを開く
  • csv.reader()関数で「データ本体を含むインスタンス」にする.ちなみにイテレータのインスタンスである.
  • イテレータのインスタンスなので,next()関数,もしくはfor文で1行ずつ読んでいく.1行が1次元の文字列のlistとして出てくるので,処理をしつつ格納する.
  • 最後にファイルをclose()する.

という流れになる.

CSVファイル内に入っている「処理したい」ターゲットが文字列の場合,今の所この標準csvライブラリを使う方法が一番適当である.

numpy.loadtxt()による読み込み

numpyで読み込む場合,CSVの中身が数字である必要がある.

流れは標準csvライブラリと同じく,codecs.open()関数でファイルを開いて,2次元配列として一気に読み込み,close()する,という流れだが,「数字である」ことが前提なので,ヘッダ等の文字列で構成されている行をskiprows=行数と「何行読み飛ばすか」を指定してから読み込み始めなければならない.

またdelimiter='区切り文字'指定により,区切り文字を明示的に指定する必要がある.(CSVは区切り文字がTABのこともあるため)

pandas.read_csv()によるpandas.DataFrame形式での読み込み

先の通り,2019年現在は,pandasを使うのが一般的.

pandasも内部的にはnumpyの配列を使っているので,やはりnumpyの2次元配列で取り出すことができるが,もっと汎用性の高いDataFrame(データフレーム)という形式で読み込むことができる.(DataFrameがpandasの最大特徴である)

さらにpandasはCSVデータをDataFrameとして読み込む時,ヘッダを特殊扱いして文字列として取り出すことができる(もちろん後述のようにnumpyと同じくヘッダを最初から読み飛ばすしてもできる).

またnumpy.loadtxt()だと強制的にfloatのみになるが,pandas.read_csv()は全て整数だった場合intの配列を作ってくれる.

さらに,標準csvライブラリやnumpy.loadtxt()のようにファイルを最初にopenして読み込み後にcloseする必要がない,numpy.loadtxt()と同じく全てのデータを一気に2次元配列として持ってくることができるが,pandasのDataFrameは,列だけを1次元numpy配列として容易に抽出できる,キーワードを与えて行や列を持ってくることができる,等の特徴がある.

さらにCSV読み込みの時は,区切り文字は自動判定される.

pandasのDataFrameは,このように非常に便利なので,基本的にはpandasのread_csvを使うと良い.

pandas以外の方法のコード例

このコードは機能をまとめてクラス化しているので,Google ColaboratoryやJupyter Notebookのようにコード単位で逐次的に実行していくものではなく,複数を一気にダウンロードして描画するなど,バッチ的に一気に処理することができる.

もちろんpandasのみを使用するときでも,クラス化しておけば,このように一気に回すことができる.

# -*- coding: utf-8 -*-
# CSVPlotter.py

import csv, numpy, pandas
import urllib.request
import codecs

# ローカルのAnacondaのPythonでグラフウィンドウを出すためには,これが必要
from PyQt5.QtWidgets import QApplication
import matplotlib.pyplot


class CSVPlotter():
    def __init__(self, url_string):
        self.__url_string = url_string

    def download_csv(self, decoder):
        # 引数decoderで指定した文字コードのCSVファイルをダウンロードして,
	# UTF-8に直して保存する
        self.__gotten_http_response = urllib.request.urlopen(self.__url_string)
        if self.__gotten_http_response.code == 200:
        # コード200が返っていてきたら正常に取得できている
            print('Sucsess to get CSV from Internet.')
            # ダウンロードしてきたデータを一度ファイルに書き込む
            self.__downloaded_filename = 'downloaded.csv'
            downloaded_file = codecs.open(self.__downloaded_filename, mode='w', encoding='utf-8')
            downloaded_file.write(self.__gotten_http_response.read().decode(decoder))
            downloaded_file.close()
            print('Sucsess to write downloaded CSV data to file.')
        else:
            # それ以外のコードが返ってきたら,異常終了
            print('Cannot get CSV file. Code:', self.__gotten_http_response.code, 'Exiting...')
            sys.exit(1)

    def read_csv_with_csv(self):
        # 標準ライブラリのcsvを使ってCSVファイルを読み込む
        print('標準のcsvライブラリで読んで表示')
        csv_file = codecs.open(self.__downloaded_filename, mode='r', encoding='utf-8')
        self.__csv_data = csv.reader(csv_file)
        
        # header以外は2次元のlistで出てくる
        # 外側のlistがRow(行),
        # 内側のリストがColumn(列)でデータ型は文字列
        header = next(self.__csv_data)
        # 1行目(データ本体ではなくデータの内容を示すヘッダ)
        print(header)
        for a_row in self.__csv_data:
            print(a_row)

        csv_file.close()
            
    def read_csv_with_numpy(self):
        # NumPyライブラリを使ってCSVファイルを読み込む
        print('NumPyライブラリで読んで表示')
        # NumPyの読み込みデータはNumPyの2次元array(ndarray)でくるので,分解して表示
        # データ型はfloat
	csv_file = codecs.open(self.__downloaded_filename, mode='r', encoding='utf-8')
        self.__csv_data = numpy.loadtxt(csv_file, delimiter=',', skiprows=1)
	csv_file.close()

        # 区切り文字を','とし,1行目(ヘッダ)を抜かして読み込む
        for a_row in self.__csv_data:
            print(a_row)
      
    def read_csv_with_pandas(self):
        # Pandsライブラリを使ってCSVファイルを読み込む
        print('Pandasライブラリで読んで表示')
        data_frame = pandas.read_csv(self.__downloaded_filename)

	# 文字列ヘッダが含まれててもエラーを起こさない
	# ヘッダだけを取り出すことができる
        header = data_frame.columns.values.tolist() #headerは標準list
        self.__csv_data = data_frame.values 
        print(header)

        # Pandsの読み込みデータもNumPyの2次元arrayでくるので,分解して表示
        # データ型は,中身が整数ならintに変換される
        for a_row in self.__csv_data:
            print(a_row)

    def make_plot_csv_data_2d(self, x_index, y_index, line_color):
        # インデックスで指定されたX軸要素とY軸要素を使い
        # NumPyのndarrayに入れて
        # Matplotlib.plotで図を描く
        plot_x_array = numpy.array([]) #空のnumpy ndarrayを生成
        plot_y_array = numpy.array([])
        for a_row in self.__csv_data:
            if isinstance(a_row[x_index], str):
                # numpy ndarrayに追加していく
                plot_x_array = numpy.append(plot_x_array, float(a_row[x_index]))
            else:
                plot_x_array = numpy.append(plot_x_array, a_row[x_index])
            if isinstance(self.__csv_data[y_index], str):
                plot_y_array = numpy.append(plot_y_array, float(self.a_row[y_index]))
            else:
                plot_y_array = numpy.append(plot_y_array, a_row[y_index])
        # plotに使うデータを設定
        matplotlib.pyplot.plot(plot_x_array, plot_y_array, color=line_color)

    def plot_show(self, x_label, y_label):
        # plotの軸の名前を設定
        matplotlib.pyplot.xlabel(x_label, fontsize=10, fontname='serif')
        matplotlib.pyplot.ylabel(y_label, fontsize=10, fontname='serif')
        # plotする
        matplotlib.pyplot.show()


if __name__ == "__main__":
    # 八王子市年齢別人口
    # http://www.city.hachioji.tokyo.jp/contents/open/002/p005866.html
    csv_url = "http://www.city.hachioji.tokyo.jp/contents/open/002/p005866_d/fil/nenreibetsu_jinkou_2703.csv"
    csv_plotter = CSVPlotter(csv_url)
    csv_plotter.download_csv('shift-jis')
    csv_plotter.read_csv_with_csv()
    csv_plotter.read_csv_with_numpy()
    csv_plotter.read_csv_with_pandas()
    csv_plotter.make_plot_csv_data_2d(1, 2, 'gray')
    csv_plotter.plot_show('Age', 'Population Size')

応用 - バッチ的に複数のCSVを処理して描画する

上記でクラス化した処理を使って,一気に複数をダウンロードし,描画する.

八王子市の年齢別人口データを年度/四半期ごとに複数持ってきて,一つのグラフに色を変えてプロットしてみる.

前述のコード例では,標準CSVライブラリで出てくるCSVのデータ形式に合わせて行ごとに読み込んだが,Google ColabやJupyterのコードのように,pandasのCSVライブラリで読み込むと,1列のみ簡単に取り出せることができる.また,ヘッダの行数を指定して読み込まない,等の処理が可能である.

コード例

# -*- coding: utf-8 -*-
# MultiCSVPlotter.py

import numpy, pandas
import urllib.request
import codecs
from PyQt5.QtWidgets import QApplication
import matplotlib.pyplot

class MultiCSVPlotter():
    def __init__(self, url_string_list):
        self.__url_string_list = url_string_list
        # numpyのndarrayで多次元配列を作るためには
        # np.array([])で初期化せずに(→append()しても連結された1次元配列になってしまう)
        # np.arange(0, x軸の最大値+1)で0〜最大値までの配列を最初に作って(X軸になる),
        # そこにvstack関数を使ってY軸になる配列を足していく形を取ると良い
        self.__csv_data_array = numpy.arange(0, 121)
        # 他のものも一応初期化しておく
        self.__column_index = 0

        return None

    def set_referring_column_index(self, column_index):
        # CSVファイルの何列目を見るか 0(1列目)~
        self.__column_index = column_index
        return self

    def download_csv_then_push_stack(self, decoder):
        # ShiftJISのCSVファイルのURL配列をダウンロードして,
        # UTF-8に直して一時保存してから,
        # pandasのCSV読み込み機能を使って読み込み,
        # ndarrayに2次元配列として入れていく
        for a_url in self.__url_string_list:
            self.__gotten_http_response = urllib.request.urlopen(a_url)
            if self.__gotten_http_response.code == 200:
                # コード200が返っていてきたら正常に取得できている
                print('Sucsess to get CSV from Internet.')
                # ダウンロードしてきたデータを一度ファイルに書き込む
                self.__downloaded_filename = 'tmp_downloaded.csv'
                downloaded_file = open(self.__downloaded_filename, mode='w', encoding='utf-8')
                downloaded_file.write(self.__gotten_http_response.read().decode(decoder))
                downloaded_file.close()
                print('Sucsess to download CSV data to file: ' + a_url)
                print('Now start to read CSV as ndarray with pandas library.')
            else:
                # それ以外のコードが返ってきたら,異常終了
                print('Cannot get CSV file. Code:', self.__gotten_http_response.code, 'Exiting...')
                sys.exit(1)

            # Pandsライブラリを使ってCSVファイルを読み込む
            # ヘッダは読み込まない指定(header=-1)
            # ヘッダは「1行」である指定(skiprows=1)
            data_frame = pandas.read_csv(self.__downloaded_filename, header=-1, skiprows=1)
            
            # まず取得した2次元配列の中から,column_indexで指定した列だけを抜き出す
            # pandasは取得したCSV,ここではdata_frameに対して,
	    # data_frame[列idnex]でその列のみの
            # 1次元配列をとり出せる.
            populationSizeArray = data_frame[self.__column_index]
            # できた1次元配列を,最初にX軸の配列で初期化した配列にvstack(())する.
            # vstackは2重括弧であることに注意
            # ただのstackでは同じ形(行と列が同じ量)の配列or行列同士しか足せないが,
            # vstackは要素数が同じ1次元配列をどんどん重ねていき
            # 多次元配列を作ることができる
            self.__csv_data_array = numpy.vstack((self.__csv_data_array, populationSizeArray))
            # ちなみにvstackの他に,hstack, column_stack, row_stackなどがある
            # これを,CSVファイル数分だけ回す
            print('Sucess to push new CSV column to stack')
        return self
        # return selfしないと,最後に実行した行の結果がreturnされるはず
        # この関数の場合はそれでもいいのだけれど
            
    def make_plot_csv_data_2d(self, line_color_list, line_legend_list):
        # Matplotlib.plotで図を描く
        # indexが1~shape(行列の次元数のtupleが得られる,ここでは(9, 121))[0]まで
        for index in range(1, self.__csv_data_array.shape[0]):
            # plotに使うデータを設定
            matplotlib.pyplot.plot(self.__csv_data_array[0], self.__csv_data_array[index], color=line_color_list[index-1], label=line_legend_list[index-1])
        #線に付与したlabel(凡例)を表示する
        matplotlib.pyplot.legend()

    def plot_show(self, x_label, y_label):
        # plotの軸の名前を設定
        matplotlib.pyplot.xlabel(x_label, fontsize=10, fontname='serif')
        matplotlib.pyplot.ylabel(y_label, fontsize=10, fontname='serif')
        # plotする
        matplotlib.pyplot.show()


if __name__ == "__main__":
    # 八王子市年齢別人口
    # http://www.city.hachioji.tokyo.jp/contents/open/002/p005866.html
    csv_url_list = list([])

    # matplotlibで使える色のリスト
    # http://matplotlib.org/examples/color/named_colors.html
    # 一応16進数カラーコードでも指定はできる
    line_color_list = list([])

    # 凡例(線の色がどの年のデータを表しているか)
    line_legend_list = list([])

    # H25 6月
    csv_url_list.append('http://www.city.hachioji.tokyo.jp/contents/open/002/p005866_d/fil/nenreibetsu_jinkou_2506.csv')
    line_color_list.append('blue')
    line_legend_list.append('H25.6')

    # H25 9月
    csv_url_list.append('http://www.city.hachioji.tokyo.jp/contents/open/002/p005866_d/fil/nenreibetsu_jinkou_2509.csv')
    line_color_list.append('green')
    line_legend_list.append('H25.9')

    # H25 12月
    csv_url_list.append('http://www.city.hachioji.tokyo.jp/contents/open/002/p005866_d/fil/nenreibetsu_jinkou_2512.csv')
    line_color_list.append('red')
    line_legend_list.append('H25.12')

    # H26 3月 (「平成25年3月末日」tと書いてあるのは25年「度」3月末……の意味らしい)
    csv_url_list.append('http://www.city.hachioji.tokyo.jp/contents/open/002/p005866_d/fil/nenreibetsu_jinkou_2503.csv')
    line_color_list.append('cyan')
    line_legend_list.append('H26.3')

    # H26 6月
    csv_url_list.append('http://www.city.hachioji.tokyo.jp/contents/open/002/p005866_d/fil/nenreibetsu_jinkou_2606.csv')
    line_color_list.append('magenta')
    line_legend_list.append('H26.6')

    # H26 9月
    csv_url_list.append('http://www.city.hachioji.tokyo.jp/contents/open/002/p005866_d/fil/nenreibetsu_jinkou_2609.csv')
    line_color_list.append('yellow')
    line_legend_list.append('H26.9')

    # H26 12月
    csv_url_list.append('http://www.city.hachioji.tokyo.jp/contents/open/002/p005866_d/fil/nenreibetsu_jinkou_2612.csv')
    line_color_list.append('black')
    line_legend_list.append('H26.12')

    # H27 3月 (同様にH26年「度」3月末の意味のようだ)
    csv_url_list.append('http://www.city.hachioji.tokyo.jp/contents/open/002/p005866_d/fil/nenreibetsu_jinkou_2703.csv')
    line_color_list.append('gray')
    line_legend_list.append('H27.3')

    csv_plotter = MultiCSVPlotter(csv_url_list)
    csv_plotter.set_referring_column_index(2)
    csv_plotter.download_csv_then_push_stack('shift-jis')
    csv_plotter.make_plot_csv_data_2d(line_color_list, line_legend_list)
    csv_plotter.plot_show('Age', 'Population Size')

[Work/Class/Python3の基礎とデータ処理/python_basic]

numpy配列(array)とmatplotlib

numpy

numpyは数字(int, float)等の配列をlistとは別の数字専用の配列で扱えるようにしたライブラリである.listとは違いC言語で書かれているため,NumPyのデータ型(数字の配列)numpy.ndarrayとnumpyに用意されている関数群を使えば,listで処理をするよりもはるかに早い計算ができる.

numpyは配列データ型ndarrayと,それを操作する静的クラス関数で構成されている.ndarrayのインスタンス関数はほぼない(インスタンス変数のshapeを使うぐらい)ので,C言語的な手続き型プログラミングのスタイルになる.

numpyの配列numpy.ndarray

numpyでは数字専用の配列numpy.ndarray(n次元配列)クラスが提供されており,そのインスタンスを用いることが前提のNumPyの関数群が用意されている.

ndarrayは一般的にコンストラクタ呼び出しで生成するのではなく,初期化用の静的クラス関数numpy.array(), numpy.empty(), numpy.zeros(), numpy.ones(), numpy.identity()などを使ってインスタンスを生成する.

numpyの配列はC言語と同じくサイズが固定されている(サイズを動的に弄れない).したがって,インスタンスを生成してくれるる静的関数.array()を呼び出す時に要素を全て入れるか,.empty()関数で形状(n x mの行列である,など)を指定する必要がある.また.empty()でデータタイプ(int, floatなど)も生成時に指定しておくと,実行時に予期せぬエラーが起きることが少なくなる.他に単位行列を作る.identity()関数もある.

import numpy
# 要素を入れてarray関数を呼び出す
my_numpy_array = numpy.array([1, 3, 5])
print(my_numpy_array)

# float型の10要素の空配列(1次元)を生成
my_numpy_array = numpy.empty(10, dtype=float)
print(my_numpy_array) 
# emptyで生成すると,適当な値が入っていることがわかる

# float型0.0の要素で埋められた3x4の2次元配列(行列)を生成
# (3, 4)と中括弧で示すのはtupleの意味
my_numpy_array = numpy.zeros((3, 4), dtype=float)
print(my_numpy_array)

# int型の0の要素で埋められた2x6の行列を生成
my_numpy_array = numpy.zeros((2, 6), dtype=int)
print(my_numpy_array)

# int型の1の要素で埋められた3x4の行列を生成
my_numpy_array = numpy.ones((3, 4), dtype=int)
print(my_numpy_array)

# 4x4のfloatの単位行列を生成
# 単位行列は2次元配列であることが自明なので,
# tupleで(4,4)を与えずに1スカラ値変数だけでいける
my_numpy_array = numpy.identity(4, dtype=float)
print(my_numpy_array)

配列や行列の各要素へのアクセス

numpy_array[何番目か]という形で大かっこ[]を使ってアクセスする.

値を読みだすだけでなく,代入もできる.

my_numpy_array = numpy.array([1, 3, 5])

a = my_numpy_array[0]  # 0番目,つまり最初の要素を取り出し,aに代入する
print(a)

my_numpy_array[2] = 7 # 2番目に7を代入する
print(my_numpy_array)

行列の場合は,numpy_array[行の番号][列の番号]という形で,大かっこを二つつなげてアクセスする.

my_numpy_array = numpy.identity(4, dtype=int) # 4*4の整数の単位行列の生成
print(my_numpy_array)


a = my_numpy_array[0][3]  # 0行目3列目の要素を取り出し,aに代入する.
print(a)

my_numpy_array[2][2] = 6 # 2行目2列目に整数の6を代入する
print(my_numpy_array)

ndarrayのサイズを取得する

numpyの静的関数ndim()にndarrayのインスタンスを突っ込むと,n次元配列のnがわかる.

my_numpy_array = numpy.identity(4, dtype=float)
print(numpy.ndim(my_numpy_array)) # =>4x4の行列は2次元配列なので,出力は「2」

ndarrayのインスタンスが持つ.shape変数(tuple型)により,そのインスタンスの各次元のサイズを取得することができる.2次元配列の場合2要素のtupleなので,それぞれ[0][1]でアクセスする.

# 3要素の1次元配列を宣言
my_numpy_array = numpy.ones((3), dtype=int) 
print(my_numpy_array.shape) # => (3, )
print(my_numpy_array.shape()[0]) # => 3
print(my_numpy_array.shape()[1]) #1次元配列なので,これはエラーになる

# 5x4要素の行列(2次元配列)を宣言
my_numpy_array = numpy.zeros((5, 4), dtype=int)
print(my_numpy_array.shape) # => (5, 4)
print(my_numpy_array.shape[0]) # => 5
print(my_numpy_array.shape[1]) # => 4

3次元配列なら3要素のtupleになるので,[0], [1], [2]でそれぞれアクセスする.

ndarrayに要素を追加する

ndarrayの静的関数としてappend()関数が用意されていて,複数の1次元配列を新たな1次元配列として連結することができる.

前述の通りndarrayのサイズは変更不可なので,append()関数で連結しても,第1引数に入れたインスタンスそのものが拡張されているわけではなく,新しいndarrayのインスタンスを返すだけなので,別の変数に代入する必要がある.

my_numpy_array = numpy.array([1, 3, 5]) # 要素1, 3, 5を持つ1次元配列のインスタンスを作成
new_my_numpy_array = numpy.append(my_numpy_array, numpy.array([7, 9, 11]))
print(new_my_numpy_array) # 連結された新しいndarrayのインスタンス
print(my_numpy_array) # もとのインスタンスは変更されていない

arange関数とndenumerate関数

標準listでいう所のrange関数に当たるのが,numpyの静的関数arange()である.使い方は同じ.

my_numpy_array = numpy.array(numpy.arange(10, 15, 0.1))
print(my_numpy_array)

またnumpy配列は,普通にfor文でも回せる.indexを取り出すときはnumpy.ndenumerate関数を使う.例えば,

numpy_array1 = numpy.arange(0, 10, 1) #0.0から10未満まで,1刻みで整数の配列を作る
numpy_array2 = numpy.zeros(10, dtype=int) # 0が10個入った1次元のnumpy配列

for index, val in numpy.ndenumerate(numpy_array1):
  numpy_array2[index] = val + 10

print(numpy_array2) 
# array1に10が足された[10 11 12 13 14 15 16 17 18 19]を出力する

という感じでfor文を書く.

numpy.ndenumerateは1次元のベクトルだけではなく,「行列にも対応できる」という点が非常に優れている.

2次元以上の場合にnumpy.ndenumerateを適用すると,indexはtuple,つまり数字の組み合わせで出てくる.大かっこでtupleを0番目(行),1番目(列)に分解する必要がある.

numpy_array1 = numpy.identity(4, dtype=int)
numpy_array2 = numpy.zeros((4, 4), dtype=int)

for index, val in numpy.ndenumerate(numpy_array1):
  print(index) # tupleで出てきていることがわかる

  row_index = index[0] # tupleを分解して,行のindexと列のindexの値にする
  column_index = index[1]

  numpy_array2[row_index][column_index] = val * 10

print(numpy_array2)

vstackによる1次元配列の積み重ねによる2次元配列の生成

例えば要素数10の配列が二つあるとして,これをもとに2x10の2次元配列(2x10の行列)を作りたい時,

my_numpy_array1 = numpy.array(numpy.arange(10, 15, 0.1))
my_numpy_array2 = numpy.array(numpy.arange(5, 10, 0.1))
print(numpy.vstack((my_numpy_array1, my_numpy_array2)))

とすると,作り出せる.vstack()関数は小括弧が二重であることに注意.(tupleを意味するので)

これまでと同じく,元の配列が拡張されるわけではなく,新たな行列のインスタンスが生成されて返される.

vstack()関数で,要素数が同じ配列なら,どんどん足していく(行列の行が増えていく)ことが可能である.例えば,

my_numpy_array = numpy.array(numpy.arange(1, 10, 0.1))
my_numpy_matrix = numpy.vstack((my_numpy_array, numpy.array(numpy.arange(2, 11, 0.1))))
my_numpy_matrix = numpy.vstack((my_numpy_matrix, numpy.array(numpy.arange(3, 12, 0.1))))
print(my_numpy_matrix) # => 3x90の行列ができている.

という感じである.

配列とスカラ値,もしくは配列同士の四則演算

配列に対してスカラ値(値が一つだけ入っている)変数を四則演算すると,各要素に対してそれが適用される

my_array = numpy.array(numpy.arange(1, 10, 2))
my_array_plus_2 = my_array + 3 # => [4 6 8 10 12]
my_array_minus_2 = my_array - 2 # => [-1 1 3 5 7]

同様に,要素数が同じ配列同士を四則演算すると,要素同士の四則演算となる.(行列演算ではないことに注意)

行列の演算

上記の計算は,配列の各要素に対して適用されるが,行列として掛け算をしたい(行列の積を求めたい)場合に静的関数の.dot()関数を使う.やはり他の変数で受けとらなければならない.

my_matrix1 = numpy.ones((4, 4), dtype=float)
my_matrix2 = numpy.identity(4, dtype=float)
my_matrix3 = numpy.dot(my_matrix1, my_matrix2)

同様にdot()関数を使うことで,ベクトル(つまり1次元配列)と行列(つまり2次元配列)の積も求めることができる.(これは2次元CGや3次元CGの座標変換などでよく使われる)

my_vector = numpy.array([1, 3.2, 5.6])
my_matrix = numpy.array([[4.2, 3.6, 2.5], [3.4, 8.9, 0.4], [0.2, 1.1, 0.5]])
print(numpy.dot(my_matrix, my_vector))

他の行列演算は,numpyのさらに中に定義されているクラスlinalgの静的関数を使う.こちらも静的関数である.

my_matrix = numpy.ones(4, dtype=float)
my_transposed_matrix = numpy.linalg.transpose(my_matrix) # 転置行列
my_inversed_matrix = numpy.linalg.inv(my_matrix) # 逆行列
my_eigenvalue = numpy.linalg.eig(my_matrix) # 行列の固有値

matplotlib

簡単に言えばグラフを書くためのライブラリである.バックエンドのGUIライブラリに何を使っているかは環境によって違うが,AnacondaやMSYS2のmingw64でインストールされるPython3用のmatplotlibでは,C++用のマルチプラットフォームGUIライブラリQtをPythonから使うための「PyQt」Ver.5が用いられている.

線のグラフ

2次元の線のグラフ(例えば折れ線グラフ,直線グラフ)を書くための手順を簡単に言えば,「X軸とY軸のnumpy配列をそれぞれ1次元のnumpy配列で作り,plot()関数で値の配列をセットし,show()関数で表示する.」だけである.

以下の例では3次関数 f(x) = -2x^3 + 8x^2 + 5を描画している.

まず線を引く際に基準となるX軸の範囲を,0から0.99の範囲まで0.01刻みで作成する.これはrange関数のnumpy版であるnumpy.arange関数を用いる.

x_asis_array = numpy.array(numpy.arange(0, 10.0, 0.01))

次に,この3次関数のyすなわちf(x)を計算する.

まず,x軸の要素数と同じy軸のnumpy配列を作る.numpy.zeros_like()関数は,与えたnumpy配列と同じ要素数で中身が全て0の配列を作るので,x_axis_arrayを与えて,numpy配列を生成する.

# x座標用と同じ要素数のゼロ配列を作る
y_axis_array = numpy.zeros_like(x_axis_array)

for文で,先ほどnumpy.arange関数を利用して作った,X軸用の値を格納しているx_asis_arrayから1つずつ値を取り出して,この計算式に入れればよいのだが,ここでnumpyの最大の特徴である「numpy配列の要素同士をまとめて計算できる」特徴を有効活用できる.

y_axis_array = -2 * numpy.power(x_axis_array, 3) + 8 * numpy.power(x_axis_array, 2) + 5

numpy.power(x, y)関数は,numpy配列の要素同士を一気に計算してくれる.1行の中(Pythonでは「式」と呼称する)に書くのであれば,上記のように複数の項があっても同時に計算してくれる.

Y軸の計算とnumpy配列の生成を1行で行う事もできる.この方法の方が要素数を間違えるなどのミスが少ないので,積極的に使うと良い.

y_axis_array = numpy.array(-2 * numpy.power(x_axis_array, 3) + 8 * numpy.power(x_axis_array, 2) + 5)

これは中身としては,for文を回すのと同じ事になる.例えば,

for x_value in x_axis_array:
  y_value = -2 * x_value **3 + 8 * x_value **2  + 5

の計算をしているのと同じことになる.

numpyにはndenumerateというenumerateのnumpy版も存在し,以下のような書き方もできるようになる.(for文を回すとなると,for文を回す前にy_axis_arrayの初期化が必要になり,このようにインデックスを使わなければ代入できないので,実際は以下のコードでないと処理が書けない)

y_axis_array = numpy.zeros_like(x_axis_array)  # Y軸の配列の0初期化

# listのenumerateのnumpy版.インデックスも同時に出してくれる.
for index, x_value in numpy.ndenumerate(x_axis_array):
  y_axis_array[index] = -2 * x_value ** 3 + 8 * x_value ** 2 + 5

このX軸の値のnumpy配列とy軸の値のnumpy配列を,matplotlib.pyplot.plot()関数に入れて,matplotlib.pyplot.show()関数を実行すると,グラフが描かれる.

matplotlib.pyplot.plot(x_axis_array, y_axis_array, color='blue')
#'blue'は描画の線の色.省略可能.
matplotlib.pyplot.show()

ここまでのコードをまとめると以下のようになる.

# -*- coding: utf-8 -*-
import numpy
import matplotlib.pyplot

if __name__ == '__main__':
    # x座標用の配列を作る
    # 0から9.99までの1000要素
    x_axis_array = numpy.array(numpy.arange(0, 10.0, 0.01))

    # Y軸の配列をnumpyでまとめて計算して,Y軸の配列を作る
    y_axis_array = numpy.array(-2 * numpy.power(x_axis_array, 3) + 8 * numpy.power(x_axis_array, 2) + 5)

    # X軸とY軸をのデータをセットして描画する
    # 2つの同じ要素数分の配列を与えると,基本的に折れ線グラフになる.
    # 色指定もできる.
    matplotlib.pyplot.plot(x_axis_array, y_axis_array, color='blue')
    # 描画したウィンドウを見せる
    matplotlib.pyplot.show()

折れ線グラフに関しては,特に意識することなくこの方法で描くことができる.試しにx軸の値の間隔を狭くして,折れ線グラフにしてみよう.

散布図

散布図を書くにはmatplotlib.pyplot.scatter関数を使う。

import numpy
import matplotlib.pyplot

x_axis_array = numpy.random.normal(loc=1.0, scale=0.5, size=100) # 平均1, 標準偏差0.5の正規分布に従う100個のランダムの値
y_axis_array = numpy.random.normal(1, 2, 100) # 引数を全て順番通りに指定するなら,どの引数に与える値なのかを省略できる

matplotlib.pyplot.scatter(x_axis_array, y_axis_array) # 散布図を描く
matplotlib.pyplot.show()

関数呼び出し時の引数の指定

numpy.random.normal関数は,平均と標準偏差を与えて,正規分布に従う乱数を指定した個数分生成する関数であるが,これまではなかった「どの引数に、どの値を与えるか」の指定をしている.

loc=scale=size=等の指定がそれである.「キーワード引数」と呼ぶ.

通常のプログラミング言語では,引数には順番があり,その順番通りに記述してやることで適切に引数を関数に渡すことができる.この場合,関数定義の時の引数の数と,関数を呼び出す時に与える引数の数が一致していなければならない.つまり基本的に同じ機能の関数であっても,引数の数が違う場合,複数の関数定義が必要となる.(関数のオーバーロードという仕組み)

一方,Pythonや最近の言語は,関数定義時に引数に名前を付けて,その名前を関数呼び出し時に指定することにより,引数の順番を任意に入れ替えることができる.(とはいえ,引数の順番はできるだけ揃えるべきである)

また標準で値が入らない引数,標準で値が入っている引数も指定することができ,普段は関数の中で標準で定められた値を使い,呼び出し側で引数で値を与えた時にのみその値をを使う,という形が実現できる.

Pythonで標準で使われるモジュールのほとんどの関数には引数に名前がついている.プログラムの分かりやすさを考えて,可能ならば引数の名前を指定した方が,可読性の高いプログラムを書くことができる.可読性が高いとは「誰が読んでもわかる」ということである.

import as

ここまで書いてくると,numpyだけならともかく,numpy.linalgクラスやmatplotlib.pyplotクラス内の静的関数を書くのが(文字数的に)面倒臭くなってくる.そこで,

import numpy as np
from numpy import linalg as la # numpyの中のlinalgクラスをimport……という意味
from matplotlib import pyplot as plt

asキーワードを使ってimportすると,その名前(この場合はnpla, plt)でそのクラスにアクセスできるようになる.

一般的にnumpyは「np」という名前で,linalglaという名前で,matplotlib.pyplotpltという名前でimportされることが多いので,慣習に従うべきである.


[Work/Class/Python3の基礎とデータ処理/python_basic]

Pythonの関数とクラスの定義

関数

プログラミング言語の関数とは,「ひとまとまりの処理を記述し,入力と出力を変数で整えることで,その処理を容易に再利用可能にしたもの」である.

数学でいう所の関数とほぼ同義である.

実はこれまで使用してきたprint(表示したい変数や文字列)というのも関数である.Pythonに標準で用意されている関数であることから,組み込み関数・ビルトイン関数などと呼ぶ.listの長さを返してくれるlen()も組み込み関数である.

関数の定義と呼び出し

自分独自の関数を定義したい場合,

def 関数名(引数をカンマで区切って定義):
    # 関数の処理内容...
    # 戻り値がある場合
    return 戻り値

というように定義する.

「引数」とは関数の入力,「戻り値」とは関数の出力である.例えば,

def increment(x):    # 関数名と引数名を定義する
  return x + 1    引数で取った値に+1をして返す

という関数が定義されている時,

a = 1
b = increment(a)  # 関数に引数aを与えて「呼び出す」
print(b)

というコードを実行すると,increment関数を引数整数1を与えて呼び出したことになり,既に定義されたincrement関数が呼び出され,1を足して返してくれる.それを変数bに代入し,printする.

従って,出力は整数の2になる.

この時,関数の定義の時に使った引数の名前(上記の例ではx)と,関数を呼び出している側の変数の名前(上記の例ではa)の名前は違ってもよい.関数を呼び出した時に,自動的に値が関数側の変数にコピーされるからである.

逆に言えば,関数と呼びだす側と関数内部の変数は全く別のものであり,同じものとして捉えるのは間違っている.関数呼び出し時に,変数内部に入っている値だけがコピーされるのである.これは戻り値についても同様である.

Pythonは関数型言語の側面も持っているので,クラスのインスタンスメンバ関数でない関数の場合,必ずreturnで何らかの値を返すようにしておく方が良い.(クラスのインスタンスメンバ関数の場合で返すものがない場合は,後述のselfを返すのが一番わかりやすい)

のように定義し呼び出す.ここでは,戻り値を受け取った変数aの中には6*2つまり12が,変数bの中には6/2つまり3が入ることになる.

引数が単純な「値」や文字列の場合,値は関数に入る時にコピーされる.しかしlistなど,単純な値以外のものを取る場合,実体(インスタンスと呼ぶ)がそのまま関数の中に引き継がれるという違いがある.

def append_apple(l):
  # listを取る関数.listの場合は,値がコピーされずに,listの実体そのままが飛んでいく
  l.append('apple')
  return l


my_list = ['grape', 'orange']
my_new_list = append_apple(my_list)
print(my_new_list)

また,関数の中でも,for文やif文をそのまま使うことができる.

def generate_list(x):
  return_list = list([])
  for item in range(x, x+10, 1): # 関数の中のfor文
    return_list.append(item)
  return return_list

a = 3
my_new_list = generate_list(a)
print(my_new_list)

Pythonでは複数の戻り値を指定することができる.例えば,

def multi_div_return(x, y):
    return x*y, x/y
    # 関数定義はここまで

# インデントを元に戻したので関数の外側
a, b = multi_div_return(6, 2)

グローバル変数

「クラスを定義してそれを駆動する」以前のPythonコードで,関数外部で宣言初期化された変数はグローバル変数となる.

変数は,その関数内部でしか通用しない.例えば違う関数の中で同じ名前の変数が宣言されていても,別の変数の扱いとなる.これをローカル変数と呼ぶ.(Pythonの変数のスコープについては前項を参照されたい)

それに対しグローバル変数は,どの関数からでもアクセスできる変数である.

関数内部でグローバル変数にアクセスするためには,アクセスする前にglobal グローバル変数名という式を実行しておく必要がある.

ただし,グローバル変数の多用は,名前がかぶってしまったり,実行する順番が明確になっていないと意図しない動作を引き起こしてしまう事が多い.グローバル変数はなるべく使用せずに,引数と戻り値で制御する方が良い.

# 関数の外側で変数を定義.グローバル変数になる.
var1 = 123

# 関数を定義する
def add_gv(x):
  global var1     # この関数内でvariable1というグローバル変数を使う事を宣言

  return var1 + x # グローバル変数を使って演算をした戻り値を返す
  # 関数定義ここまで

a = 789
b = add_gv(a)
print(b)          # 123 + 789で912がbの中には入っている

既にある関数やクラスの読み込み

自分で定義した関数やクラスではなくとも,関数やクラスをまとめたモジュールが既に存在し,それを読み込み,利用することができる.

例えば,数学的な関数や定数が定義されているmathモジュールを読み込むときには,

import math

という風にimportキーワードを使って,読み込みを行う.データ分析の大体の部分は既存のモジュールのみで可能である.

読み込んだ後は,モジュール名.モジュールで定義されている定数や,モジュール名.モジュールで定義されている関数などのように,「.」を付けて個別の定数や関数を呼び出すことができる.

print(math.pi) # mathモジュール内で定義済みの円周率の定数

a = 4
b = math.sqrt(4) # math.sqrtは,平方根を返してくれる関数.mathモジュール内で定義済み.
print(b)

Google Colaboratoryのような環境(逐次実行できる環境 - REPL環境と呼ぶ)では,一度importすると,他のセルでも読み込んだモジュールは有効である.ただし接続制限時間というものがあり,ウィンドウを閉じてしばらく経ったり,何も操作せずにしばらく経ったり,または長時間計算をすると,Googleが提供しているサーバとの接続が切れて再起動される.その時は再度importする必要がある.

Notebookの最初のセルにたとえば「このセルを最初に必ず実行!」という風に書いて,importをしておくと良い.

クラス

クラスとは,関数や定数,保持するべき内部パラメータなど必要な機能をひとまとめにしたものである.

関数との大きな違いは,クラスはオブジェクトインスタンス化(単にインスタンス化とも)することで,保持すべき内部パラメータ……データすなわち「状態」をまとめて保持できることにある.インスタンス関数がクラスにまとめられるのはむしろ,この「状態」にアクセスするためにである.この「保持されている状態」はインスタンス変数と呼ばれる.

またクラスは,「保持されている状態」には関係しない,似たような機能を持つ定数や関数をまとめる機能を持ち,それぞれクラス変数,静的関数・クラス関数と呼ばれる.

Pythonをデータ分析に用いる場合,殆どのデータ分析用のクラスは既にあるので新たに自分で定義する必要は殆どない.

クラスの定義

class クラス名(親クラス):
    # クラス定義の内容...

と定義する.親クラスがない時(正確にはobjectクラスが親の時)は,小括弧の中はobjectにする,空にする,小括弧をつけない,のどれかを選択する.

selfキーワード

Javaでthisに相当する「このクラスの」もしくは「このインスタンスの」を表すキーワードはselfである.

コンストラクタの定義

def __init__(self, コンストラクタが取る変数...):
    # コンストラクタ関数内の処理...

と書くことで,クラスのコンストラクタを定義する.

コンストラクタは「何も返さない」ことが決められているので,return Noneを最後に実行する.Noneキーワードに注意.

内部で親クラスのコンストラクタを実行したい時には,

super().__init__(親クラスのコンストラクタの引数からselfを除いた引数)

という形で親クラスのコンストラクタにアクセスする.(Python2では書法が異なる)

インスタンスメンバ変数の定義

コンストラクタや他の関数内部でself.変数名と宣言すると,インスタンスメンバ変数となる.

クラスのインスタンスメンバ変数は,基本的にprivateであるべきである.privateな変数の定義は,変数名がアンダースコア2つ連続で始まる規則になっており,__variable_nameと書かれるので,インスタンスメンバ変数はself.__variable_nameと定義する.

インスタンスメンバ関数の定義

インスタンスメンバ関数の定義では,第一引数が必ずselfになる.ただし呼び出しの時は第一引数を書かずに第二引数から書き始める.

クラス変数と静的関数・クラス関数

クラス変数

静的変数・定数つまりインスタンスを生成しなくても使えるクラス内の定数(Javaでいう所のpublic static定数)は,selfをつけずに,コンストラクタや関数外で宣言すればよい.

class MyClass:
  クラス変数の名前 = 値

という形で宣言する.クラスの外からは

クラス名.クラス変数の名前

でアクセスする.

クラス「変数」という名前ではあるが,実際は定数として運用する.そのクラスの中の静的関数を利用する際に有用となる定数が定義されている事が多い.前述の数学的な関数や定数が定義されているmathモジュールでは,円周率が定義されており,事前にimportしておけば,

print(math.pi)

という形で呼び出すことができる.

静的関数

静的関数は,データを実行対象として直接紐づけずに,実行時にデータを与える関数であり,与えたデータ例えばlistを破壊的に操作することはなく,たいていは新しいオブジェクトインスタンスを作って,そこに元のオブジェクトインスタンスからコピーを行い,操作を加えて,戻り値として返してくれる.

Pythonでの静的関数は,一般的にC言語のみで書かれた高速ライブラリで採用されている.通常のオブジェクト指向プログラミング言語ではオブジェクトインスタンスを作り操作を行うような場合でも,Pythonのライブラリでは静的関数として実装されていることも多い.numpyが代表的である.C言語の機能を直接実走したものに,このパターンが多い.

前述の数学の関数や定数が定義されているmathモジュールでは,三角関数が用意されており,事前にimportしておけば,

b = math.sin(a)
d = math.cos(c)

の要に呼び出すことができる.

自分でクラスを定義する場合の静的関数は以下のように宣言する.

@staticmethod
def my_function(引数):
    # 処理内容....

静的関数はselfを引数に取らないので,書かない.つまり静的関数は(当たり前だが)インスタンスメンバ変数にはアクセスできない.

クラス関数

上記の静的関数他に,Pythonには「クラス関数」(クラスメソッド)というものもある.これは第一引数にselfを取る静的関数のことで,静的変数にも内部的にアクセスできる.が,ややこしくなるので書かない方がよい.クラスの静的定数には「クラス名.定数名」でアクセスする方が明確である.

ソースコードが関数定義やクラス定義から始まる時のmain関数

Pythonのソースコードは,上から順次実行されるが,関数定義やクラス定義がある場合,まず初めに関数定義やクラス定義を書いて,実行開始main関数を次に書く.main関数の定義は以下のように行う.

# ...
# ここまでクラス定義

if __name__ == '__main__':
   # ソースコードの実行開始時に読まれる関数
   # この中でクラスのインスタンスを作り,処理する.
   # ...

自分でクラスを定義する時のコード例

以下は,PyQtというGUIライブラリを使ったグラフィック表示の例である.データ分析ではクラスを自分で定義することはほとんどないので,参考程度に眺めておけばよい.

コード中では,

  1. 必要なクラスライブラリの読み込み
  2. 自分で定義するクラスの定義
  3. main関数

の順で進む.

# -*- coding: utf-8 -*-
# BounceAndColoredBall.py

# 必要なクラスライブラリの読み込み
import sys # 今回はアプリケーション起動時の引数を取ってくるために使う
import math # 数学関係
import random # ランダム用ライブラリ

# GUIに使うQt5のライブラリ
# 本筋とは関係ないので,「そんなもんか」と捉えておけば良い
from PyQt5.QtCore import * 
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


# 自分のクラスの定義
class BounceBall():
    # コンストラクタ
    # 引数の頭が必ずselfになることに注意
    def __init__(self, windowWidth, windowHeight):
        self.__windowWidth = windowWidth #privateメンバ変数は「self.__変数名」
        self.__windowHeight = windowHeight
        self.__x_pos = math.floor(random.random() * self.__windowWidth)
        self.__y_pos = math.floor(random.random() * self.__windowHeight)
        if random.random() > 0.5 :
            self.__x_direction = 1
        else:
            self.__x_direction = -1
        if random.random() > 0.5 :
            self.__y_direction = 1
        else:
            self.__y_direction = -1

        return None # コンストラクタはNoneを返すと決められている

    def updateParameters(self):
        self.__x_pos += 10 * self.__x_direction
        if self.__x_pos > self.__windowWidth :
            self.__x_direction = -1
        elif self.__x_pos < 0 :
            self.__x_direction = 1

        self.__y_pos += 10 * self.__y_direction
        if self.__y_pos > self.__windowHeight :
            self.__y_direction = -1
        elif self.__y_pos < 0 :
            self.__y_direction = 1

        return self

    def get_x(self):
        return self.__x_pos

    def get_y(self):
        return self.__y_pos


class ColoredBall(BounceBall): # BounceBallを継承して,色情報を持たせたクラス
    # コンストラクタのオーバーライド
    def __init__(self, windowWidth, windowHeight):
        # 最初に親クラス(BounceBall)のコンストラクタを呼び出す
        super().__init__(windowWidth, windowHeight)

        # 子クラス独自のコンストラクタの内容を書いていく
        self.__r_color = math.floor(random.random() * 155) + 100
        self.__g_color = math.floor(random.random() * 155) + 100
        self.__b_color = math.floor(random.random() * 155) + 100
	
	return None

    # 子クラス独自の関数を定義
    def get_r(self):
        return self.__r_color
    def get_g(self):
        return self.__g_color
    def get_b(self):
        return self.__b_color

# 実際に描画するウィンドウを呼び出して描画するクラス(JavaではJFrameに相当する)
# 本筋には関係ないので「こんなもんか」と眺めるだけで良い
class MyWidget(QWidget):
    # コンストラクタのオーバーライド
    def __init__(self, parent=None):
        super().__init__(parent)

        self.__ball_list = list([])

        for i in range(10):
            a_ball = BounceBall(640, 480)
            self.__ball_list.append(a_ball)

        self.__colored_ball_list = list([])
        for i in range(10):
            a_ball = ColoredBall(640, 480)
            self.__colored_ball_list.append(a_ball)

        self.resize(640, 480)
        self.show()

	return None


    # 描画イベント関数(Processingでいうdraw関数)のオーバーライド
    def paintEvent(self, event):
        painter = QPainter(self) # QPainterのインスタンスを作成
        painter.setPen(Qt.black) # Stroke(枠線)に相当
        # 画面のRefresh
        painter.setBrush(Qt.white) # 中の色に相当
        painter.drawRect(0, 0, 640, 480);

        for a_ball in self.__ball_list:
            a_ball.updateParameters()
            painter.drawEllipse(a_ball.get_x(), a_ball.get_y(), 20, 20)

        for a_ball in self.__colored_ball_list:
            a_ball.updateParameters()
            painter.setBrush(QColor(a_ball.get_r(), a_ball.get_g(), a_ball.get_b()))
            painter.drawEllipse(a_ball.get_x(), a_ball.get_y(), 20, 

	# 最後にupdate関数を呼び出すと描画される
        self.update()

# main関数        
if __name__ == '__main__':
        app = QApplication(sys.argv)
        w = MyWidget() # 自分で作ったクラスのインスタンスを作る
        w.raise_()
        app.exec_() #paintEventが回るようにする

[Work/Class/Python3の基礎とデータ処理]

Python3の基礎とデータ処理

この授業の目的

ビッグデータを使いたい場合を想定して「既にCSVとしてダウンロードできるデータを使う」ための,プログラム言語Pythonを使ったデータ処理の方法と統計の基礎についてを学ぶ.

実際の分析では,「データが少量の時に,表計算ソフトウェアで対話的にデータを整える」場合と,「大量のデータが存在する場合にデータを整える処理の部分もプログラムで自動化する」場合の2種類のテキストを用意した.

「プログラムなんか書かなくても,全部Excelでポチポチ対話的にやればいいじゃない.後ろの方はいらない」と思うかもしれないが,ビッグデータを使いたい場合,そもそもデータが大量である.CSVの行や列が1万もあった場合に,いちいちExcelで開いてちょこちょこ操作してというのを,さらに1万シート分も繰り返すのはとてもできない.そのような場合には「データを整える部分」プログラムで自動化する必要がある.

また,音楽の場合は,一つの音符ごとに計算をしなければならなかったりなど,本当に大量のデータを処理する必要がある.

「定型処理をまとめて繰り返す」のはプログラミングの得意技である.そこでプログラミングも一緒に学ぶ.

概要

近年PythonがそれまでのMATLABやR言語に代わって,データ処理に使われることが多くなった.また海外では教育用言語として90年代末から普及が始まり,現在様々なフレームワークが開発されているWebサーバ側をはじめとしたサーバ用途と,通常のデスクトップのスクリプト処理用途,両用のLL(Lightweight Language)として使われている.

Pythonの特徴として「Python本体はスクリプト言語だが,ライブラリをC言語で実装しPythonにAPIを用意することで,高速に実行可能」という点がある.近年ではデータ解析や機械学習などで頻繁にPythonが使われているが,これはこの「Cで書かれた高速ライブラリをPythonで実行」というスタイルに依るものである.

現在のPythonは大きく分けてVer.2.x系とVer.3系の2つが使われているが,本授業ではPython3を対象とする.(OSX標準のPythonは2.7なので,授業の下準備としてAnacondaをインストールしておくこと)

コンテンツ

Pythonの基礎

  1. Pythonの基本と配列(list)の取り扱い
  2. 関数とクラスの定義
  3. numpy配列(array)とmatplotlib
  4. CSVの取得とPlot,pandas.DataFrameの取り扱い
  5. 文字列の取り扱い
  6. lambda式,高階関数,内包表記
  7. HTMLParserクラスによるWebページの取得と分析

表計算ソフトウェアを使って対話的にデータを整える場合

  1. CSVデータを加工して相関係数を算出
  2. CSVデータを加工して単純線形回帰分析
  3. CSVデータを加工してt検定
  4. CSVデータを加工して分散分析と多重比較
  5. CSVデータを加工して重回帰分析と因果関係
  6. CSVデータを加工して主成分分析
  7. CSVデータを加工して線形二項分類
  8. CSVデータを加工して因子分析

大量のデータがある時にプログラムを書いてデータを整える処理を自動化する場合

  1. CSVデータからの相関係数の算出
  2. CSVデータからの単純線形回帰分析
  3. CSVデータからのt検定
  4. CSVデータからの分散分析と多重比較
  5. CSVデータからの重回帰分析と因果関係
  6. CSVデータからの主成分分析
  7. CSVデータからの線形二項分類
  8. CSVデータからの因子分析

授業の下準備

Google Colaboratoryを試用する場合(インストール不要,OS不問)

このページの内容は,Googleが提供している,Webブラウザから実行できるPythonの環境「Google Colaboratory」で全て実行可能である.従ってこのページの内容を学習するために自分のコンピュータにPythonの環境を整える必要はない.

C言語のツールや,他の環境(例えばアート系であればCycling'74のJavaScript環境)との通信・連動を行いたい場合は,自分のコンピュータ内に実行環境を整える必要があるため,後述のAnacondaをインストールするのがよい.

Windows

Anacondaを使う場合

Anacondaは現在標準となっているPythonのデータアナリシスディストリビューションである.こちらを使うのが一番楽.

Anacondaダウンロードページから,「64-Bit Graphical Installer」をダウンロードする.

インストール画面1

「Next」

インストール画面2

「I Agree」

インストール画面3

「All Users」の方が実は楽.管理者パスワードがわからないときには「Just Me」

インストール画面4

インストール場所に半角スペースなどが含まれているとエラーになるので,そのまま.もしくはCドライブ直下にするなど.

インストール画面5

上の方(システムパスに追加)は,システム的に混乱する可能性があるので外して置いた方がいい.

逆に下はVisual Studio等のWindowsコンパイラのみに設定を与えるもので,GPUの利用などを考えているなら,チェックを入れておく.(基本的にチェックを入れて置いて大丈夫)

インストール画面6

インストールが進む.

インストール画面7

終わったら「Next」

インストール画面8

Visual Studio Codeというエディタを追加インストールするか訊かれる.Visual Studio Communityが既に入っていたり,VS Codeを使わないなら「Skip」

インストール画面9

「Finish」

WindowsでMSYSを使う場合

CやC++のツールと連携させたい場合のみ(VSのコンパイラが必要なCUDA系は除く),Cコンパイラとセットになるこちらを使う.MSYSを使ってインストールしたPythonは文字コードがWindowsのもの縛りになるので注意.データ分析ならAnacondaの方が使い勝手は良い.

まっさらな状態からのMSYS2+GCCでWindows上にC言語とC++の環境を整えるの通りにコンパイラ環境を整える.

その後「MSYS2 MSYS」ショートカットで起動する端末エミュレータから,

$ pacman -S mingw64/mingw-w64-x86_64-python3
$ pacman -S mingw64/mingw-w64-x86_64-python3-numpy
$ pacman -S mingw64/mingw-w64-x86_64-python3-scipy
$ pacman -S mingw64/mingw-w64-x86_64-python3-matplotlib
$ pacman -S mingw64/mingw-w64-x86_64-python3-pandas

の五つのパッケージをインストールしておく.依存関係にある必要なライブラリ(主にQt関係)も全て一緒に入ってくれる.(64bit Windowsの場合)

Pythonの実行時には,MSYS2 MSYSから,

 $ /mingw64/bin/python3 MyPythonCode.py

と実行する.

OSX, macOS

OSX,macOSはPython本体とnumpy, scipy, matplotlibは標準で入っているのだが,バージョンが2.7である.HomebrewなどでPython3を入れるという方法もあるが,Homebrewでインストールを行うとシステム全体に影響を及ぼし,元々入っていたPython2.7とごちゃ混ぜになりシステムにダメージを与える可能性が高い.

そこでデータ処理に特化したPythonのパッケージであるAnacondaを「HDDのアプリケーション」以下にインストールして使う.Anacondaは/Applications/anacondaフォルダ内で独立したファイルツリーを持つ.

Python3を使いたい場合はAnacondaのPythonを明示的に実行してやる形にすれば,通常のシステムの処理に必要なPythonは元々システムに入っていた2.7がそのまま使われることになる.この方法で,システムに必要なPython2.7と,プログラミング言語として使いたいPython3系を,安全に同居させることができる.

Anacondaのダウンロードページの「Download for macOS」から「Python 3.6 version」の「Graphical Installer」をダウンロードする.

ダウンロードされた.pkgを実行して,ライセンスに同意し,「インストール先を変更」して「特定のディスク」の「アプリケーション」フォルダにインストールする.そうするとマシンの「/Applications」に「anaconda」フォルダ内にanacondaがインストールされ,Terminal.appから実行するPythonはこの中のPythonを使うように設定される.

Anaconda3のインストールパッケージ一覧の画面 Anaconda3のライセンス表示 Anaconda3のライセンス同意 Anaconda3「インストール先を変更」 Anaconda3「特定のディスクにインストール」を選択 Anaconda3メインのシステムHDDが選択されていることを確認し「フォルダを選択」 Anaconda3 フォルダを選択.ハードディスク直下の「アプリケーション」 Anaconda3 選択終了「続ける」

「このユーザがTerminal.appを開いた時はAnacondaのPythonを使う」という設定が記述されている~/.bash_profileからexport PATH=/Applications/anaconda...という行を削除しておき,Python3を実行する時は「Terminal.app」から,

 $ /Applications/anaconda/bin/python MyPythonCode.py

と「Anacondaのpython」を明示的に実行するようにしておくと,システム的に混乱が起きない.

OSXのPython2.7には,この授業の目的である基本的なデータ解析で使うnumpy, matplotlib, scipyも標準で含まれているのだが,matplotlibが使うGUI部品(システム標準はおそらくTk, Anacondaや上記WindowsのMSYS2環境ではQt5)や,リストを使ったイテレータの言語仕様などが違うため,Python2.7と3で互換性がないプログラムもある.

Anacondaの環境を作って実行環境のターミナルを開く

Pythonはライブラリがたくさんあり,衝突するものもある.Anacondaは複数の「環境environment」を作り,「環境」ごとにライブラリをインストールすることができるため,ライブラリの衝突を防ぐことができる.

ここでは授業用の環境「for_class」を作ってみる.

環境を作る

「Environment」タブにして,下の「Create」ボタン.

環境の名前をつける

環境の名前(ここでは"for_class")をつけて,「Create」.

環境が作られている

環境が作られている.

再生ボタンからOpen Terminal

環境の作成が終わったら,作成した環境の再生ボタンから「Open Terminal」.

Terminalが開いて実行できる

Terminalが開いて実行できるようになるので,プログラムが置いてあるフォルダにcdコマンドで移動して,

python 実行したいpythonプログラムファイル.py

で実行できるようになる.

Anaconda-Navigatorでの追加ライブラリのインストール

AnacondaはGUIでライブラリが追加インストールできる.ここでは例としてTwitterのAPIを使うために必要なOauth認証に必要なrequests_oauthlibをインストールする.

conda-forgeというレポジトリ(AnacondaではChannelと呼称する)がよくメンテされているようなので,それを追加して,Anacondaから使えるようにする.

まず管理者権限をもつユーザでAnaconda-Navigatorを起動する.

管理者権限を持つユーザでAnaconda-Navigatorを起動する

「Environment」(環境)を選択→「当該プロジェクトで使っているAnacondaの環境(ここではrootだが,基本的には前述の通りプロジェクトごとに環境を作る)」が選択されていることを確認→「Channels」ボタンを押す.

環境を選択しChannelを追加する

ミニウィンドウが開くので「Add」

ミニウィンドウが開く

新たなフィールドに「conda-forge」チャンネルを入力.

新たなフィールドに「conda-forge」チャンネルを入力

追加したら「Update channels」

「Update channels」

もとの画面に戻るので「Update Index」すると,下のバーでIndexをアップデートしている進行状況が表示される.

「Update Index」

一番左のプルダウンメニューから「Not Installed」(まだインストールされていないライブラリの検索)→一番右のボックスに「ライブラリの名前」(ここでは「requests-oauthlib」)を入力すると,下のフィールドに検索結果が出てくる.

「Not Installed」→「ライブラリの名前入力」→検索結果がでる

ライブラリにチェックを入れて,「Apply」

ライブラリにチェックを入れて「Apply」

進行状況のミニウィンドウが出る.

進行状況のミニウィンドウ

入れたいライブラリに必要なライブラリ(依存関係と呼称する)が全て並んで出てくるので「Apply」.

依存関係の表示

プルダウンメニューを「Installed」にして,インストールされていることを確認する.

「Installed」で確認.

以上である.Environment→rootの再生マークからターミナルを呼び出しても使えるし,root環境に入れておけば,通常のターミナルから/Applications/anaconda/bin/python3でPythonインタプリタを呼び出した時もライブラリが使える.

Anacondaで環境をたくさん作り,使用するライブラリを切り替えることもできる.