À l'origine, j'ai appris le langage R lorsque j'ai appris l'apprentissage automatique au Shizuoka Developers Study Group en 2013, mais après cela, j'ai appris «[Sazae-san's Janken Data Analysis]» (http: //yaju3d.hatenablog) une seule fois par an. .jp / entry / 2017/01/03/134420) ", je viens de démarrer R Studio, et j'ai l'impression de me souvenir de l'opération. L'année dernière, j'ai pu Préparer l'environnement de développement Python avec Visual Studio Code, j'ai donc essayé de le porter du langage R vers Python. J'ai fait. Cela dit, c'était la première fois pour moi de travailler sérieusement avec Python, donc j'ai eu du mal.
[PostScript 31/12/2018] Selon Livre blanc Sazae-san Janken édition hiver 2017, le premier (trimestre) cool (janvier, avril, juillet, octobre) ) Il est facile d'obtenir du choki, donc cette fois j'ai essayé de l'intégrer.
pip install beautifulsoup4
pip install pandasql
C'était la première fois que je faisais du scraping Web avec Python, alors je l'ai recherché et l'ai trouvé sous le nom Télécharger les données Janken de Sazae (et Precure) Le script a été publié sur Git Hub, je l'ai donc utilisé comme référence. Cette fois, Pandas est utilisé pour la sortie dans un fichier CSV.
[PostScript du 01/01/2018] "Les études Janken de Sazae-san" a pris fin le 2017/06/25, donc après 2017/07 Les données ne peuvent pas être obtenues. Merci pour un long moment m (_ _) m Les données qui suivent sont ajoutées manuellement à partir des Résultats du jeu avec Sazae (annuel).
GetSazaeData.py
# -*- coding: utf-8 -*-
#get data from http://www.asahi-net.or.jp/~tk7m-ari/sazae_ichiran.html
'''
Acquisition des données de prévision Janken de Sazae
'''
import urllib.request
import datetime as dt
import bs4 as bs
import pandas as pd
def normalized_year(year):
'''
Modifier l'année à 2 chiffres en année à 4 chiffres
'''
return int(year) + 2000 if year < 91 else int(year) + 1900
def read_data():
'''
Acquisition de données par web scraping
'''
result = []
response = urllib.request.urlopen('http://www.asahi-net.or.jp/~tk7m-ari/sazae_ichiran.html')
soup = bs.BeautifulSoup(response, "lxml")
for i in soup.body.contents[9].contents:
if i.string and len(i.string.strip()) != 0:
split = i.strip().split()
seq = int(split[0][1:-1])
year, month, day = map(int, split[1].split('.'))
year = normalized_year(year)
#the data contain illegal date: 91.11.31 -> 91.12.01
if year == 1991 and month == 11 and day == 31:
date = dt.date(year, month + 1, 1)
else:
date = dt.date(year, month, day)
kind, idx = ('-', 9)
hand = split[2]
if hand == 'Goo':
kind, idx = ('G', 1)
if hand == 'Choki':
kind, idx = ('C', 2)
if hand == 'Par':
kind, idx = ('P', 3)
result.append((seq, year, date, kind, idx))
result.reverse()
return result
def main():
'''
Principale
'''
df_data = pd.DataFrame(read_data(), columns=['seq', 'year', 'date', 'kind', 'idx'])
df_data.to_csv('SazaeData.csv', index=False)
if __name__ == '__main__':
main()
La sortie "SazaeData.csv" par GetSazaeData.py est lue et les résultats gagnants / perdants pour les 10 années de 2009 à 2018 sont affichés. Je ne semble pas m'habituer à la manipulation de données pandas, donc j'utilise "pandasql" pour manipuler les données en utilisant SQL. De plus, "pysqldf", qui est un fork de pandasql qui vous permet d'utiliser des fonctions définies par l'utilisateur, est également bon.
main.py
# -*- coding: utf-8 -*-
'''
Prédiction Janken de Sazae
'''
import datetime
import pandas as pd
from pandasql import sqldf
def get_guess(fstkind, sndkind, thrkind):
'''
Prochaine prédiction
'''
guess = 'G'
if fstkind == 'G':
guess = 'C'
elif fstkind == 'C':
guess = 'G'
elif fstkind == 'P':
guess = 'G'
#Quand il y a 2 front
if sndkind != '':
if sndkind != fstkind:
#Combinaison différente: je m'attends à ce que les mains restantes sortent, alors je ferai le reste
ptn = fstkind + sndkind
if ptn in('GC', 'CG'):
guess = 'C' #Faites-le C en attendant P
elif ptn in('CP', 'PC'):
guess = 'P' #Faire P avec l'attente de G
elif ptn in('PG', 'GP'):
guess = 'G' #Faire G avec l'attente de C
else:
#S'ils sont les mêmes, je m'attends à ce qu'ils soient égoïstes, alors je vais perdre
if fstkind == 'G':
guess = 'C' #Faites-le C en attendant P
elif fstkind == 'C':
guess = 'P' #Faire P avec l'attente de G
elif fstkind == 'P':
guess = 'G' #Faire G avec l'attente de C
#Quand il y a 3 front
if thrkind != '':
#Combinaison différente: je m'attends à ce que les mains restantes sortent, alors je ferai le reste
ptn = fstkind + sndkind
if ptn in('GC', 'CG'):
guess = 'C' #Puisque P sort, réglez-le sur C
ptn = fstkind + sndkind + thrkind
if ptn in('GCG', 'CGC'):
guess = 'C' #Faites-le C en attendant P
elif ptn in('CPC', 'PCP'):
guess = 'P' #Faire P avec l'attente de G
elif ptn in('PGP', 'GPG'):
guess = 'G' #Faire G avec l'attente de C
elif ptn in('GGC', 'CCG', 'GCC', 'CGG'):
guess = 'C' #Faites-le C en attendant P
elif ptn in('CCP', 'PPC', 'PCC', 'CPP'):
guess = 'P' #Faire P avec l'attente de G
elif ptn in('PPG', 'GGP', 'GPP', 'PGG'):
guess = 'G' #Faire G avec l'attente de C
return guess #Valeur de retour
def get_fight(kind, guess):
'''
Création de la fonction victoire / perte
'''
ptn = kind + guess
if ptn in('GP', 'CG', 'PC'):
result = 'win'
elif kind == guess:
result = 'draw'
else:
result = 'lose'
return result #Valeur de retour
def isFirstWeek(value):
'''
1,4,7,Jugement s'il s'agit de la première semaine de 10
'''
date = datetime.datetime.strptime(value, '%Y-%m-%d')
if((date.month - 1) % 3 != 0):
return False
day = date.day
weeks = 0
while day > 0:
weeks += 1
day -= 7
return (weeks == 1)
def get_fight_result(df_data):
'''
Gains / pertes avec données historiques par année
'''
result = []
i = 0
oldyear = 0
row = len(df_data)
while i < row:
if oldyear != df_data.ix[i, 'year']:
oldyear = df_data.ix[i, 'year']
thrkind, sndkind, fstkind = ['', '', '']
seq = df_data.ix[i, 'seq']
year = df_data.ix[i, 'year']
date = df_data.ix[i, 'date']
kind = df_data.ix[i, 'kind']
#Obtenez le prochain mouvement
guess = get_guess(fstkind, sndkind, thrkind)
#1,4,7,Il y a beaucoup de choki dans la première semaine de 10
if(isFirstWeek(date)):
guess = 'G'
fight = get_fight(kind, guess)
thrkind, sndkind, fstkind = [sndkind, fstkind, kind]
result.append((seq, year, date, kind, guess, fight))
i = i + 1
return pd.DataFrame(result, columns=['seq', 'year', 'date', 'kind', 'guess', 'fight'])
def get_winning_percentage(df_data):
'''
Calcul du taux de gain annuel
'''
result = []
i = 0
oldyear = 0
row = len(df_data)
while i < row:
if oldyear != df_data.ix[i, 'year']:
oldyear = df_data.ix[i, 'year']
year = oldyear
draw = df_data.ix[i, 'cnt']
lose = df_data.ix[i+1, 'cnt']
win = df_data.ix[i+2, 'cnt']
rate = round(win / (win + lose), 3)
result.append((year, win, lose, draw, rate))
i = i + 1
return pd.DataFrame(result, columns=['year', 'win', 'lose', 'draw', 'rate'])
def main():
'''
Principale
'''
#Lire les données Janken de Sazae
ytbl = pd.read_csv('SazaeData.csv')
#Gain / perte avec les données passées pendant 10 ans
pd.set_option("display.max_rows", 100)
query = "SELECT seq, year, date, kind, idx FROM ytbl WHERE idx<>9 AND year BETWEEN 2009 AND 2018;"
ytblptn = sqldf(query, locals())
fighttbl = get_fight_result(ytblptn)
print(fighttbl)
#Calcul du taux de gain annuel pendant 10 ans
query = "SELECT year,fight,COUNT(fight) AS cnt FROM fighttbl GROUP BY year,fight ORDER BY year;"
fightcnt = sqldf(query, locals())
ratetbl = get_winning_percentage(fightcnt)
print(ratetbl)
if __name__ == '__main__':
main()
Parce que c'est long, la prédiction de la main de Sazae 2018 et le résultat de la victoire / défaite
seq | year | date | kind | guess | fight | |
---|---|---|---|---|---|---|
443 | 1364 | 2018 | 2018-01-07 | C | G | win |
444 | 1365 | 2018 | 2018-01-14 | G | G | draw |
445 | 1366 | 2018 | 2018-01-21 | C | C | draw |
446 | 1367 | 2018 | 2018-01-28 | G | C | lose |
447 | 1368 | 2018 | 2018-02-04 | P | C | win |
448 | 1369 | 2018 | 2018-02-11 | G | G | draw |
449 | 1370 | 2018 | 2018-02-18 | C | G | win |
450 | 1371 | 2018 | 2018-02-25 | C | C | draw |
451 | 1372 | 2018 | 2018-03-04 | P | C | win |
452 | 1373 | 2018 | 2018-03-11 | G | P | win |
453 | 1374 | 2018 | 2018-03-18 | G | G | draw |
454 | 1375 | 2018 | 2018-03-25 | C | G | win |
455 | 1376 | 2018 | 2018-04-01 | C | G | win |
456 | 1377 | 2018 | 2018-04-08 | G | C | lose |
457 | 1378 | 2018 | 2018-04-15 | P | C | win |
458 | 1379 | 2018 | 2018-04-22 | P | G | lose |
459 | 1380 | 2018 | 2018-04-29 | C | G | win |
460 | 1381 | 2018 | 2018-05-06 | G | P | win |
461 | 1382 | 2018 | 2018-05-13 | C | C | draw |
462 | 1383 | 2018 | 2018-05-20 | P | C | win |
463 | 1384 | 2018 | 2018-05-27 | G | P | win |
464 | 1385 | 2018 | 2018-06-03 | C | G | win |
465 | 1386 | 2018 | 2018-06-10 | G | C | lose |
466 | 1387 | 2018 | 2018-06-17 | P | C | win |
467 | 1388 | 2018 | 2018-06-24 | P | G | lose |
468 | 1389 | 2018 | 2018-07-01 | C | G | win |
469 | 1390 | 2018 | 2018-07-08 | G | P | win |
470 | 1391 | 2018 | 2018-07-15 | P | C | win |
471 | 1392 | 2018 | 2018-07-22 | G | G | draw |
472 | 1393 | 2018 | 2018-07-29 | C | G | win |
473 | 1394 | 2018 | 2018-08-05 | C | C | draw |
474 | 1395 | 2018 | 2018-08-12 | P | C | win |
475 | 1396 | 2018 | 2018-08-19 | G | P | win |
476 | 1397 | 2018 | 2018-08-26 | G | G | draw |
477 | 1398 | 2018 | 2018-09-02 | P | G | lose |
478 | 1399 | 2018 | 2018-09-09 | C | G | win |
479 | 1400 | 2018 | 2018-09-16 | G | P | win |
480 | 1401 | 2018 | 2018-09-23 | C | C | draw |
481 | 1402 | 2018 | 2018-09-30 | P | C | win |
482 | 1403 | 2018 | 2018-10-07 | C | G | win |
483 | 1404 | 2018 | 2018-10-14 | G | P | win |
484 | 1405 | 2018 | 2018-10-21 | P | C | win |
485 | 1406 | 2018 | 2018-11-04 | P | G | lose |
486 | 1407 | 2018 | 2018-11-11 | C | G | win |
487 | 1408 | 2018 | 2018-11-18 | C | P | lose |
488 | 1409 | 2018 | 2018-11-25 | G | P | win |
489 | 1410 | 2018 | 2018-12-02 | G | C | lose |
490 | 1411 | 2018 | 2018-12-09 | P | C | win |
491 | 1412 | 2018 | 2018-12-16 | C | G | win |
Résultats victoires / défaites pour 2009-2018
year | win | lose | draw | rate | |
---|---|---|---|---|---|
0 | 2009 | 32 | 5 | 12 | 0.865 |
1 | 2010 | 27 | 6 | 14 | 0.818 |
2 | 2011 | 30 | 8 | 12 | 0.789 |
3 | 2012 | 27 | 12 | 10 | 0.692 |
4 | 2013 | 26 | 11 | 12 | 0.703 |
5 | 2014 | 32 | 8 | 11 | 0.800 |
6 | 2015 | 34 | 8 | 8 | 0.810 |
7 | 2016 | 26 | 12 | 12 | 0.684 |
8 | 2017 | 34 | 8 | 6 | 0.810 |
9 | 2018 | 30 | 9 | 10 | 0.769 |
Les trames de données en langage R pourraient également être facilement portées à l'aide des pandas de Python. sqldf pourrait également être remplacé par pandasql. Si quoi que ce soit, il était plus difficile de réduire les erreurs d'avertissement dans Pylint par Visual Studio Code. Même si je cherchais à partir du contenu de l'erreur, je ne pouvais pas accéder au site écrit en japonais, donc je l'ai corrigé tout en comprenant le texte anglais. Vous devez comprendre les conventions de dénomination de Python.
Recommended Posts