SlideShare une entreprise Scribd logo
1  sur  23
Télécharger pour lire hors ligne
データヴィジュアライズのための 
簡単なWeb API開発まめ知識 
2014 Shizuoka.py #4
自己紹介 
♪ オーイシ(@oec014) 
♪ dogrun Inc. 
♪ 電子書籍(企画・デザイン等) 
現在は読書の補助&拡張ツールの開発… 
♪データマイニング、ビジュアライズなど
今回の資料は… 
• 特に、とにかく簡単にWeb APIを作ってみたい!とい 
う人向けです。 
• データセットを見てどのように実装できるか、デザイン 
できるかなど、作業を見通すためにも、普段サービス構 
築に関わらない人もAPIの理解を深めることがサービス 
構築にとても立つはず。 
• PythonのORマッパーつかうと簡単にできます。
つぶやきの音楽情報集めてます 
• Twitterで#nowplaying されたつぶやきを集めて、アーティスト、楽 
曲のランキングを作っています。(beatcaster.net) 
• 音楽そのものの価値に加えて、コンテンツへの言及やユーザーの関わ 
り方がコンテンツ波及の重要な要素になると考えています。ユーザー 
のコンテンツへの関わり(コンテクスト)の情報がさらにコンテン 
ツの消費を広げる要素になるような情報配信を模索しています。 
• TWでは、季節に関連して集中して聞かれる(つぶやかれる)曲を見 
かけます。「この日にこの曲がよく聞かれる」というような情報がコ 
ンテンツの波及に有効かも。
試しに「この日に聞かれる音楽」の 
Web APIを作ってみました 
• 日本語のつぶやきに限定して、1日に27000~2900程 
度の音楽がTwitterで#nowplayingされます。このつぶ 
やきを2年分集計しました。 
• つぶやきから機械的に曲名、アーティスト名抽出をして 
います。正規化していない…のでノイズ多めです。 
• 『つぶやきの量』&TFIDFで『特定の日の特定の曲のつ 
ぶやきの重みの指標』をJSONで返します。
musicinfo_count 
DataFrame 
特定日のTWをカウント 
NPs 
(ある日の総TW数) 
DataFrameで集計 
ある曲のTWが有った日 
をカウント 
Days 
(TWのあった日数) 
tfidfの値をupdate 
ただし10TW/day以 
上の曲に限る。 
musicinfo_all 
MySQL 
TW数をカウント 
musicinfo_count 
MySQL 
tfidf = (count/NPs) * log( 1/(Days/365) ) 
TFIDF集計プロセス
musicinfo_count 
day: VARCHAR 
count: INT 
song: VARCHAR 
artist: VARCHAR 
tfidf: FLOAT 
import_ja 
user: VARCHAR 
id: BIGINT 
day: VARCHAR 
txt: VARCHAR 
musicinfo 
song/artist 抽出: 
musicinfo_all 
user: VARCHAR 
date: DATE 
song: VARCHAR 
artist: VARCHAR 
txt: VARCHAR 
count: 
count 
1日に10件以上のデータのある 
song-artistの組み合わせのみ登録 
tfidf集計: 
get tfidf 
update 
category 
artist: VARCHAR 
category: VARCHAR 
API用データベースの概念モデル
df = pd.DataFrame(dic, columns=['id', 'count', 'tfidf']) 
plt.scatter(df['count'], df['tfidf']) 
plt.show() 
TW数 
TFIDF
APIサーバを簡単に作るために… 
ORマッパーを使います。 
• Webサービス構築にORMを使うとデータベースとの接 
続処理を専用のクラスに任せ、その処理を意識せずオブ 
ジェクトの追加や取り出しができるようになります。 
• 今回の例では自分が軽量フレームワークのFlaskとのセッ 
トでよく使っている”SQLAlchemyで”サンプルのサービ 
スを作っています。
モデルの定義とセッションの初期化 
テーブル定義とクラスマッピング 
from sqlalchemy import Table, Column, Integer, String, Float 
from sqlalchemy.ext.declarative import declarative_base 
Base = declarative_base() 
class Music(Base): 
__tablename__ = 'musicinfo_count' 
id = Column(Integer, primary_key=True) 
day = Column(String(12)) 
song = Column(String(100)) 
artist = Column(String(200)) 
count = Column(Integer) 
tfidf = Column(Float) 
def __init__(self, id, day, song, artist, count, tfidf): 
self.id = id 
self.day = day 
self.song = song 
self.artist = artist 
self.count = count 
self.tfidf = tfidf 
class ArtistCategory(Base): 
__tablename__ = 'artist_category' 
id =Column(Integer, primary_key=True) 
artist = Column(String(200)) 
category = Column(String(10)) 
def __init__(self, artist, category): 
self.artist = artist 
self.category = category モジュールを作りアプリケーション内で使いまわします。
モデルの定義とセッションの初期化 
セッションの作成 
##~いろいろ省略 
from sqlalchemy import create_engine, Date, and_, or_ 
from sqlalchemy.orm import sessionmaker, join 
from music import Music, Base, ArtistCategory 
from marshmallow import fields, Schema, Serializer 
import json 
##~いろいろ省略 
! 
Session = sessionmaker() 
engine = create_engine('mysql://root:xxx@localhost/xxx',encoding='utf-8)') 
Base.metadata.create_all(engine) 
Session.configure(bind=engine) 
session = Session() 
SQLAlchemy のSessionは「ORMとデータベースとの対話を全て担当して、データベース 
から読み出したり生成したマッピングインスタンスを保存しておく場所」とのこと。
ORMを使ったデータの取得 
単純なselect 
SQL では 
select * from Music; 
! 
SQLAlchemyでは 
result = session.query(Music).all() 
! 
※SQLAlchemyでは、Sessionのquery() メソッドを 
使ってQueryオブジェクトを生成します。
ORMを使ったデータの取得 
filterによる条件指定のパターン 
• 単純な問い合わせ。all()を実行することでDBに実際に問い合わせが発生する。 
session.query(Model).filter(Model.objectname == “hoo”).all() 
• カンマ区切りでAND条件を指定 
session.query(Model).filter(Model.object1==“hoo”, Model.object2==‘’bar” 
• filterメソッドの複数指定でAND条件 
session.query(Model).filter(Model.id==1).filter(Model.name==“hoo”).allI() 
• OR条件 
session.query(Model).filter(or_(Model.id==1, Model.name==“foo”).all() 
• ORとANDの組み合わせ 
session.query(Model).filter(or_(Model.id==1, Model.name==“hoo”), Model.value==1).all() 
• SQL文を指定 
session.execute(“SELECT * from musicinfo_count”) 
• LIKEによる部分一致 
session.querry(Model).filter(Model.name.like(‘%hoge%’).allI() 
• IN演算子 
session.query(Model).filter(Model.id.in_([1,2,3])).all() 
• BETWEEN演算子 
session.query(Model).filter(Model.value.between(1,3)
ORMを使ったデータの取得 
単純な条件指定でのデータ取得の例 
@app.route('/feature') 
def getRanking(): 
days = request.args.get("byday") 
if days: 
mu = session.query(Music).filter(Music.day.like('%'+ days +’%’))  
.order_by(Music.tfidf.desc()).all()
ORMを使ったデータの取得 
marshmallowによるデータのシリアライズ 
from marshmallow import fields, Schema, Serializer 
import json 
! 
##~諸々省略 
@app.route('/feature') 
def getRanking(): 
days = request.args.get("byday") 
if days: 
mu = session.query(Music).filter(Music.day.like('%'+ days +’%')). 
order_by(Music.tfidf.desc()).all() 
serialized = muserializer(mu, many=True).data 
return json.dumps(serialized, ensure_ascii=False).encode('utf-8') 
! 
class muserializer(Serializer): 
class Meta: 
fields = ("song", "artist","count", "tfidf")
musicinfo_count 
day: VARCHAR 
count: INT 
song: VARCHAR 
artist: VARCHAR 
tfidf: FLOAT 
import_ja 
user: VARCHAR 
id: BIGINT 
day: VARCHAR 
txt: VARCHAR 
musicinfo 
song/artist 抽出: 
musicinfo_all 
user: VARCHAR 
date: DATE 
song: VARCHAR 
artist: VARCHAR 
txt: VARCHAR 
count: 
count 
1日に10件以上のデータのある 
song-artistの組み合わせのみ登録 
tfidf集計: 
get tfidf 
update 
category 
artist: VARCHAR 
category: VARCHAR 
API用データベースの概念モデル
musicinfo_count 
marshmallow 
query 
category 
JSON生成のプロセス 
day: VARCHAR 
count: INT 
song: VARCHAR 
artist: VARCHAR 
tfidf: FLOAT 
SQLAlchemy 
filter() 
API (getRanking) 
song: 
artist: 
count: 
tfidf: 
category: 
json 
byday: %m-%d 
d: %d 
m: %m 
c:[idol, voice actor, その他] 
artist: VARCHAR 
category: VARCHAR
別テーブルの項目の追加 
内部結合を含む条件指定 
単純な内部結合はテーブルとカラムを指定し、 
filter()メソッドを複数AND条件で結合する。 
! 
session.query(ArtistCategory). 
filter(Music.artist==ArtistCategory.artist).filter(Music.artist==artist).all() 
! 
!
別テーブルの項目の追加 
queryのリスト化 
複合的な条件指定にクエリをリスト化する方法があります。 
検索条件が複雑になったときのフィルタを書きやすいかも。 
def getRanking2(): 
d = request.args.get("d") 
m = request.args.get("m") 
c = request.args.get("c") 
params = [] 
if d: 
md = m + "-" + d 
params.append(Music.artist==ArtistCategory.artist) 
params.append(Music.day==md) 
params.append(ArtistCategory.category==c) 
p = and_(*params) 
mu = session.query(Music).filter(p).all() 
serialized = mucatserializer(mu, many=True).data 
return json.dumps(serialized, ensure_ascii=False).encode('utf-8') 
filterの条件をリストに追加し 
and_メソッドで条件を結合した後 
リストをfilterメソッドに渡します。
別テーブルの項目の追加 
シリアライザで項目をJSONに追加する 
class mucatserializer(Serializer): 
category = fields.Method("get_category") 
def get_category(self, Music): 
ar = Music.artist 
return getcategory(ar) 
class Meta: 
fields = ("song", "artist", "count", "tfidf", "category") 
def getcategory(artist): 
name = session.query(ArtistCategory).filter(Music.artist==ArtistCategory.artist) 
.filter(Music.artist==artist).all() 
if name: 
return name[0].category 
else: 
return "" 
シリアライザ内でArtistCategoryテーブルの 
結合した項目を取得し追加ます。
別テーブルの項目の追加 
AND と ORの複合条件 
if ct: 
cts = ct.split(',') 
if len(cts) == 1: 
if "other" in ct: 
params.append(ArtistCategory.category=="") 
elif "VA" in ct: 
params.append(ArtistCategory.category=="VA") 
elif "IDOL" in ct: 
params.append(ArtistCategory.category=="IDOL") 
elif len(cts) == 2: 
param = (ArtistCategory.category==cts[0]) 
for item in cts: 
param = param | (ArtistCategory.category==item) 
params.append(param) 
md = m + "-" + d 
params.append(Music.artist==ArtistCategory.artist) 
params.append(Music.day==md) 
p = and_(*params) 
mu = session.query(Music).filter(p).all() 
serialized = mucatserializer(mu, many=True).data 
return json.dumps(serialized, ensure_ascii=False).encode('utf-8') 
OR条件でリストに追加 
AND条件でリストに追加
D3.js 
データをAPIをD3.jsを使って視覚化してみます
次回Shizuoka.pyがあるならやりたいこと… 
RDF Triplestore用のORMとして、SQLAlchemyと近いコードで記述でき 
る”RDFAlchemy”があるようです。 
! 
>>> c = Company.query.get_by(symbol = 'IBM') 
>>> print(c.companyName) 
International Business Machines Corp.

Contenu connexe

Similaire à Shizuokapy4_データヴィジュアライズのための簡単なWeb API開発まめ知識

ASP.NET シングル ページ アプリケーション (SPA) 詳説
ASP.NET シングル ページ アプリケーション (SPA) 詳説ASP.NET シングル ページ アプリケーション (SPA) 詳説
ASP.NET シングル ページ アプリケーション (SPA) 詳説Akira Inoue
 
10分で分かるr言語入門ver2.14 15 0905
10分で分かるr言語入門ver2.14 15 090510分で分かるr言語入門ver2.14 15 0905
10分で分かるr言語入門ver2.14 15 0905Nobuaki Oshiro
 
10分で分かるr言語入門ver2.15 15 1010
10分で分かるr言語入門ver2.15 15 101010分で分かるr言語入門ver2.15 15 1010
10分で分かるr言語入門ver2.15 15 1010Nobuaki Oshiro
 
Apexコアデベロッパーセミナー070726 配布用
Apexコアデベロッパーセミナー070726 配布用Apexコアデベロッパーセミナー070726 配布用
Apexコアデベロッパーセミナー070726 配布用stomita
 
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)Toru Kawamura
 
マッシュアップ勉強会
マッシュアップ勉強会マッシュアップ勉強会
マッシュアップ勉強会guestadcb01
 
マッシュアップ勉強会
マッシュアップ勉強会マッシュアップ勉強会
マッシュアップ勉強会seiryo
 
20160928_「Cloud Robotics Azure Platform 基本セット」構築ハンズオン
20160928_「Cloud Robotics Azure Platform 基本セット」構築ハンズオン20160928_「Cloud Robotics Azure Platform 基本セット」構築ハンズオン
20160928_「Cloud Robotics Azure Platform 基本セット」構築ハンズオンIoTビジネス共創ラボ
 
PhpでMySqlを使う
PhpでMySqlを使うPhpでMySqlを使う
PhpでMySqlを使うpcod
 
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみようAlfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみようTasuku Otani
 
WebAPIではじめるphp入門
WebAPIではじめるphp入門WebAPIではじめるphp入門
WebAPIではじめるphp入門Hiroaki Murayama
 
夏サミ2012 [A-2]ソーシャルプラットフォームを使った業務アプリ開発の現場
夏サミ2012 [A-2]ソーシャルプラットフォームを使った業務アプリ開発の現場夏サミ2012 [A-2]ソーシャルプラットフォームを使った業務アプリ開発の現場
夏サミ2012 [A-2]ソーシャルプラットフォームを使った業務アプリ開発の現場Mitch Okamoto
 
ピクサー USD 入門 新たなコンテンツパイプラインを構築する
ピクサー USD 入門 新たなコンテンツパイプラインを構築するピクサー USD 入門 新たなコンテンツパイプラインを構築する
ピクサー USD 入門 新たなコンテンツパイプラインを構築するTakahito Tejima
 
オフラインファーストの思想と実践
オフラインファーストの思想と実践オフラインファーストの思想と実践
オフラインファーストの思想と実践Shumpei Shiraishi
 
WebIDLを見てみる
WebIDLを見てみるWebIDLを見てみる
WebIDLを見てみるtakenspc
 
XPagesDay 2015 RESTの総復習
XPagesDay 2015 RESTの総復習XPagesDay 2015 RESTの総復習
XPagesDay 2015 RESTの総復習Masahiko Miyo
 
広告配信現場で使うSpark機械学習
広告配信現場で使うSpark機械学習広告配信現場で使うSpark機械学習
広告配信現場で使うSpark機械学習x1 ichi
 
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法decode2016
 

Similaire à Shizuokapy4_データヴィジュアライズのための簡単なWeb API開発まめ知識 (20)

ASP.NET シングル ページ アプリケーション (SPA) 詳説
ASP.NET シングル ページ アプリケーション (SPA) 詳説ASP.NET シングル ページ アプリケーション (SPA) 詳説
ASP.NET シングル ページ アプリケーション (SPA) 詳説
 
10分で分かるr言語入門ver2.14 15 0905
10分で分かるr言語入門ver2.14 15 090510分で分かるr言語入門ver2.14 15 0905
10分で分かるr言語入門ver2.14 15 0905
 
10分で分かるr言語入門ver2.15 15 1010
10分で分かるr言語入門ver2.15 15 101010分で分かるr言語入門ver2.15 15 1010
10分で分かるr言語入門ver2.15 15 1010
 
Apexコアデベロッパーセミナー070726 配布用
Apexコアデベロッパーセミナー070726 配布用Apexコアデベロッパーセミナー070726 配布用
Apexコアデベロッパーセミナー070726 配布用
 
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
 
マッシュアップ勉強会
マッシュアップ勉強会マッシュアップ勉強会
マッシュアップ勉強会
 
マッシュアップ勉強会
マッシュアップ勉強会マッシュアップ勉強会
マッシュアップ勉強会
 
20160928_「Cloud Robotics Azure Platform 基本セット」構築ハンズオン
20160928_「Cloud Robotics Azure Platform 基本セット」構築ハンズオン20160928_「Cloud Robotics Azure Platform 基本セット」構築ハンズオン
20160928_「Cloud Robotics Azure Platform 基本セット」構築ハンズオン
 
20120118 titanium
20120118 titanium20120118 titanium
20120118 titanium
 
PhpでMySqlを使う
PhpでMySqlを使うPhpでMySqlを使う
PhpでMySqlを使う
 
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみようAlfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
 
WebAPIではじめるphp入門
WebAPIではじめるphp入門WebAPIではじめるphp入門
WebAPIではじめるphp入門
 
夏サミ2012 [A-2]ソーシャルプラットフォームを使った業務アプリ開発の現場
夏サミ2012 [A-2]ソーシャルプラットフォームを使った業務アプリ開発の現場夏サミ2012 [A-2]ソーシャルプラットフォームを使った業務アプリ開発の現場
夏サミ2012 [A-2]ソーシャルプラットフォームを使った業務アプリ開発の現場
 
ピクサー USD 入門 新たなコンテンツパイプラインを構築する
ピクサー USD 入門 新たなコンテンツパイプラインを構築するピクサー USD 入門 新たなコンテンツパイプラインを構築する
ピクサー USD 入門 新たなコンテンツパイプラインを構築する
 
オフラインファーストの思想と実践
オフラインファーストの思想と実践オフラインファーストの思想と実践
オフラインファーストの思想と実践
 
WebIDLを見てみる
WebIDLを見てみるWebIDLを見てみる
WebIDLを見てみる
 
XPagesDay 2015 RESTの総復習
XPagesDay 2015 RESTの総復習XPagesDay 2015 RESTの総復習
XPagesDay 2015 RESTの総復習
 
Data API 2.0
Data API 2.0Data API 2.0
Data API 2.0
 
広告配信現場で使うSpark機械学習
広告配信現場で使うSpark機械学習広告配信現場で使うSpark機械学習
広告配信現場で使うSpark機械学習
 
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
 

Plus de Nao Oec

Pgx user meeting_20170602
Pgx user meeting_20170602Pgx user meeting_20170602
Pgx user meeting_20170602Nao Oec
 
Lodチャレンジ2016 エリアベンチマーキング資料
Lodチャレンジ2016 エリアベンチマーキング資料Lodチャレンジ2016 エリアベンチマーキング資料
Lodチャレンジ2016 エリアベンチマーキング資料Nao Oec
 
Shizuoka.py #6 WebTestでWeb APIのテスト & Pythonメタプログラミングでテストの自動生成
Shizuoka.py #6 WebTestでWeb APIのテスト & Pythonメタプログラミングでテストの自動生成Shizuoka.py #6 WebTestでWeb APIのテスト & Pythonメタプログラミングでテストの自動生成
Shizuoka.py #6 WebTestでWeb APIのテスト & Pythonメタプログラミングでテストの自動生成Nao Oec
 
PGXでつぶやきの類似度によるグラフを生成してみた
PGXでつぶやきの類似度によるグラフを生成してみたPGXでつぶやきの類似度によるグラフを生成してみた
PGXでつぶやきの類似度によるグラフを生成してみたNao Oec
 
RESASを使った静岡市の新しい産業の創成手法サンプル
RESASを使った静岡市の新しい産業の創成手法サンプルRESASを使った静岡市の新しい産業の創成手法サンプル
RESASを使った静岡市の新しい産業の創成手法サンプルNao Oec
 
Python neo4j cytoscapejsでデータ可視化入門
Python neo4j cytoscapejsでデータ可視化入門Python neo4j cytoscapejsでデータ可視化入門
Python neo4j cytoscapejsでデータ可視化入門Nao Oec
 
Dockerで作るd3.jsインタラクション共有&DL環境
Dockerで作るd3.jsインタラクション共有&DL環境Dockerで作るd3.jsインタラクション共有&DL環境
Dockerで作るd3.jsインタラクション共有&DL環境Nao Oec
 
コンピュータビジョン7章資料_20140830読書会
コンピュータビジョン7章資料_20140830読書会コンピュータビジョン7章資料_20140830読書会
コンピュータビジョン7章資料_20140830読書会Nao Oec
 
Open streetmapハンズオン@静岡まとめ
Open streetmapハンズオン@静岡まとめOpen streetmapハンズオン@静岡まとめ
Open streetmapハンズオン@静岡まとめNao Oec
 
Shizuokapy 3 oec_nlp
Shizuokapy 3 oec_nlpShizuokapy 3 oec_nlp
Shizuokapy 3 oec_nlpNao Oec
 
iLeafletとは何か
iLeafletとは何かiLeafletとは何か
iLeafletとは何かNao Oec
 

Plus de Nao Oec (11)

Pgx user meeting_20170602
Pgx user meeting_20170602Pgx user meeting_20170602
Pgx user meeting_20170602
 
Lodチャレンジ2016 エリアベンチマーキング資料
Lodチャレンジ2016 エリアベンチマーキング資料Lodチャレンジ2016 エリアベンチマーキング資料
Lodチャレンジ2016 エリアベンチマーキング資料
 
Shizuoka.py #6 WebTestでWeb APIのテスト & Pythonメタプログラミングでテストの自動生成
Shizuoka.py #6 WebTestでWeb APIのテスト & Pythonメタプログラミングでテストの自動生成Shizuoka.py #6 WebTestでWeb APIのテスト & Pythonメタプログラミングでテストの自動生成
Shizuoka.py #6 WebTestでWeb APIのテスト & Pythonメタプログラミングでテストの自動生成
 
PGXでつぶやきの類似度によるグラフを生成してみた
PGXでつぶやきの類似度によるグラフを生成してみたPGXでつぶやきの類似度によるグラフを生成してみた
PGXでつぶやきの類似度によるグラフを生成してみた
 
RESASを使った静岡市の新しい産業の創成手法サンプル
RESASを使った静岡市の新しい産業の創成手法サンプルRESASを使った静岡市の新しい産業の創成手法サンプル
RESASを使った静岡市の新しい産業の創成手法サンプル
 
Python neo4j cytoscapejsでデータ可視化入門
Python neo4j cytoscapejsでデータ可視化入門Python neo4j cytoscapejsでデータ可視化入門
Python neo4j cytoscapejsでデータ可視化入門
 
Dockerで作るd3.jsインタラクション共有&DL環境
Dockerで作るd3.jsインタラクション共有&DL環境Dockerで作るd3.jsインタラクション共有&DL環境
Dockerで作るd3.jsインタラクション共有&DL環境
 
コンピュータビジョン7章資料_20140830読書会
コンピュータビジョン7章資料_20140830読書会コンピュータビジョン7章資料_20140830読書会
コンピュータビジョン7章資料_20140830読書会
 
Open streetmapハンズオン@静岡まとめ
Open streetmapハンズオン@静岡まとめOpen streetmapハンズオン@静岡まとめ
Open streetmapハンズオン@静岡まとめ
 
Shizuokapy 3 oec_nlp
Shizuokapy 3 oec_nlpShizuokapy 3 oec_nlp
Shizuokapy 3 oec_nlp
 
iLeafletとは何か
iLeafletとは何かiLeafletとは何か
iLeafletとは何か
 

Shizuokapy4_データヴィジュアライズのための簡単なWeb API開発まめ知識

  • 2. 自己紹介 ♪ オーイシ(@oec014) ♪ dogrun Inc. ♪ 電子書籍(企画・デザイン等) 現在は読書の補助&拡張ツールの開発… ♪データマイニング、ビジュアライズなど
  • 3. 今回の資料は… • 特に、とにかく簡単にWeb APIを作ってみたい!とい う人向けです。 • データセットを見てどのように実装できるか、デザイン できるかなど、作業を見通すためにも、普段サービス構 築に関わらない人もAPIの理解を深めることがサービス 構築にとても立つはず。 • PythonのORマッパーつかうと簡単にできます。
  • 4. つぶやきの音楽情報集めてます • Twitterで#nowplaying されたつぶやきを集めて、アーティスト、楽 曲のランキングを作っています。(beatcaster.net) • 音楽そのものの価値に加えて、コンテンツへの言及やユーザーの関わ り方がコンテンツ波及の重要な要素になると考えています。ユーザー のコンテンツへの関わり(コンテクスト)の情報がさらにコンテン ツの消費を広げる要素になるような情報配信を模索しています。 • TWでは、季節に関連して集中して聞かれる(つぶやかれる)曲を見 かけます。「この日にこの曲がよく聞かれる」というような情報がコ ンテンツの波及に有効かも。
  • 5. 試しに「この日に聞かれる音楽」の Web APIを作ってみました • 日本語のつぶやきに限定して、1日に27000~2900程 度の音楽がTwitterで#nowplayingされます。このつぶ やきを2年分集計しました。 • つぶやきから機械的に曲名、アーティスト名抽出をして います。正規化していない…のでノイズ多めです。 • 『つぶやきの量』&TFIDFで『特定の日の特定の曲のつ ぶやきの重みの指標』をJSONで返します。
  • 6. musicinfo_count DataFrame 特定日のTWをカウント NPs (ある日の総TW数) DataFrameで集計 ある曲のTWが有った日 をカウント Days (TWのあった日数) tfidfの値をupdate ただし10TW/day以 上の曲に限る。 musicinfo_all MySQL TW数をカウント musicinfo_count MySQL tfidf = (count/NPs) * log( 1/(Days/365) ) TFIDF集計プロセス
  • 7. musicinfo_count day: VARCHAR count: INT song: VARCHAR artist: VARCHAR tfidf: FLOAT import_ja user: VARCHAR id: BIGINT day: VARCHAR txt: VARCHAR musicinfo song/artist 抽出: musicinfo_all user: VARCHAR date: DATE song: VARCHAR artist: VARCHAR txt: VARCHAR count: count 1日に10件以上のデータのある song-artistの組み合わせのみ登録 tfidf集計: get tfidf update category artist: VARCHAR category: VARCHAR API用データベースの概念モデル
  • 8. df = pd.DataFrame(dic, columns=['id', 'count', 'tfidf']) plt.scatter(df['count'], df['tfidf']) plt.show() TW数 TFIDF
  • 9. APIサーバを簡単に作るために… ORマッパーを使います。 • Webサービス構築にORMを使うとデータベースとの接 続処理を専用のクラスに任せ、その処理を意識せずオブ ジェクトの追加や取り出しができるようになります。 • 今回の例では自分が軽量フレームワークのFlaskとのセッ トでよく使っている”SQLAlchemyで”サンプルのサービ スを作っています。
  • 10. モデルの定義とセッションの初期化 テーブル定義とクラスマッピング from sqlalchemy import Table, Column, Integer, String, Float from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Music(Base): __tablename__ = 'musicinfo_count' id = Column(Integer, primary_key=True) day = Column(String(12)) song = Column(String(100)) artist = Column(String(200)) count = Column(Integer) tfidf = Column(Float) def __init__(self, id, day, song, artist, count, tfidf): self.id = id self.day = day self.song = song self.artist = artist self.count = count self.tfidf = tfidf class ArtistCategory(Base): __tablename__ = 'artist_category' id =Column(Integer, primary_key=True) artist = Column(String(200)) category = Column(String(10)) def __init__(self, artist, category): self.artist = artist self.category = category モジュールを作りアプリケーション内で使いまわします。
  • 11. モデルの定義とセッションの初期化 セッションの作成 ##~いろいろ省略 from sqlalchemy import create_engine, Date, and_, or_ from sqlalchemy.orm import sessionmaker, join from music import Music, Base, ArtistCategory from marshmallow import fields, Schema, Serializer import json ##~いろいろ省略 ! Session = sessionmaker() engine = create_engine('mysql://root:xxx@localhost/xxx',encoding='utf-8)') Base.metadata.create_all(engine) Session.configure(bind=engine) session = Session() SQLAlchemy のSessionは「ORMとデータベースとの対話を全て担当して、データベース から読み出したり生成したマッピングインスタンスを保存しておく場所」とのこと。
  • 12. ORMを使ったデータの取得 単純なselect SQL では select * from Music; ! SQLAlchemyでは result = session.query(Music).all() ! ※SQLAlchemyでは、Sessionのquery() メソッドを 使ってQueryオブジェクトを生成します。
  • 13. ORMを使ったデータの取得 filterによる条件指定のパターン • 単純な問い合わせ。all()を実行することでDBに実際に問い合わせが発生する。 session.query(Model).filter(Model.objectname == “hoo”).all() • カンマ区切りでAND条件を指定 session.query(Model).filter(Model.object1==“hoo”, Model.object2==‘’bar” • filterメソッドの複数指定でAND条件 session.query(Model).filter(Model.id==1).filter(Model.name==“hoo”).allI() • OR条件 session.query(Model).filter(or_(Model.id==1, Model.name==“foo”).all() • ORとANDの組み合わせ session.query(Model).filter(or_(Model.id==1, Model.name==“hoo”), Model.value==1).all() • SQL文を指定 session.execute(“SELECT * from musicinfo_count”) • LIKEによる部分一致 session.querry(Model).filter(Model.name.like(‘%hoge%’).allI() • IN演算子 session.query(Model).filter(Model.id.in_([1,2,3])).all() • BETWEEN演算子 session.query(Model).filter(Model.value.between(1,3)
  • 14. ORMを使ったデータの取得 単純な条件指定でのデータ取得の例 @app.route('/feature') def getRanking(): days = request.args.get("byday") if days: mu = session.query(Music).filter(Music.day.like('%'+ days +’%’)) .order_by(Music.tfidf.desc()).all()
  • 15. ORMを使ったデータの取得 marshmallowによるデータのシリアライズ from marshmallow import fields, Schema, Serializer import json ! ##~諸々省略 @app.route('/feature') def getRanking(): days = request.args.get("byday") if days: mu = session.query(Music).filter(Music.day.like('%'+ days +’%')). order_by(Music.tfidf.desc()).all() serialized = muserializer(mu, many=True).data return json.dumps(serialized, ensure_ascii=False).encode('utf-8') ! class muserializer(Serializer): class Meta: fields = ("song", "artist","count", "tfidf")
  • 16. musicinfo_count day: VARCHAR count: INT song: VARCHAR artist: VARCHAR tfidf: FLOAT import_ja user: VARCHAR id: BIGINT day: VARCHAR txt: VARCHAR musicinfo song/artist 抽出: musicinfo_all user: VARCHAR date: DATE song: VARCHAR artist: VARCHAR txt: VARCHAR count: count 1日に10件以上のデータのある song-artistの組み合わせのみ登録 tfidf集計: get tfidf update category artist: VARCHAR category: VARCHAR API用データベースの概念モデル
  • 17. musicinfo_count marshmallow query category JSON生成のプロセス day: VARCHAR count: INT song: VARCHAR artist: VARCHAR tfidf: FLOAT SQLAlchemy filter() API (getRanking) song: artist: count: tfidf: category: json byday: %m-%d d: %d m: %m c:[idol, voice actor, その他] artist: VARCHAR category: VARCHAR
  • 18. 別テーブルの項目の追加 内部結合を含む条件指定 単純な内部結合はテーブルとカラムを指定し、 filter()メソッドを複数AND条件で結合する。 ! session.query(ArtistCategory). filter(Music.artist==ArtistCategory.artist).filter(Music.artist==artist).all() ! !
  • 19. 別テーブルの項目の追加 queryのリスト化 複合的な条件指定にクエリをリスト化する方法があります。 検索条件が複雑になったときのフィルタを書きやすいかも。 def getRanking2(): d = request.args.get("d") m = request.args.get("m") c = request.args.get("c") params = [] if d: md = m + "-" + d params.append(Music.artist==ArtistCategory.artist) params.append(Music.day==md) params.append(ArtistCategory.category==c) p = and_(*params) mu = session.query(Music).filter(p).all() serialized = mucatserializer(mu, many=True).data return json.dumps(serialized, ensure_ascii=False).encode('utf-8') filterの条件をリストに追加し and_メソッドで条件を結合した後 リストをfilterメソッドに渡します。
  • 20. 別テーブルの項目の追加 シリアライザで項目をJSONに追加する class mucatserializer(Serializer): category = fields.Method("get_category") def get_category(self, Music): ar = Music.artist return getcategory(ar) class Meta: fields = ("song", "artist", "count", "tfidf", "category") def getcategory(artist): name = session.query(ArtistCategory).filter(Music.artist==ArtistCategory.artist) .filter(Music.artist==artist).all() if name: return name[0].category else: return "" シリアライザ内でArtistCategoryテーブルの 結合した項目を取得し追加ます。
  • 21. 別テーブルの項目の追加 AND と ORの複合条件 if ct: cts = ct.split(',') if len(cts) == 1: if "other" in ct: params.append(ArtistCategory.category=="") elif "VA" in ct: params.append(ArtistCategory.category=="VA") elif "IDOL" in ct: params.append(ArtistCategory.category=="IDOL") elif len(cts) == 2: param = (ArtistCategory.category==cts[0]) for item in cts: param = param | (ArtistCategory.category==item) params.append(param) md = m + "-" + d params.append(Music.artist==ArtistCategory.artist) params.append(Music.day==md) p = and_(*params) mu = session.query(Music).filter(p).all() serialized = mucatserializer(mu, many=True).data return json.dumps(serialized, ensure_ascii=False).encode('utf-8') OR条件でリストに追加 AND条件でリストに追加
  • 23. 次回Shizuoka.pyがあるならやりたいこと… RDF Triplestore用のORMとして、SQLAlchemyと近いコードで記述でき る”RDFAlchemy”があるようです。 ! >>> c = Company.query.get_by(symbol = 'IBM') >>> print(c.companyName) International Business Machines Corp.