[PYTHON] Introduction aux statistiques de quiz (1) -Analyse mathématique des phrases de questions pour connaître la tendance des questions-

introduction

Est-ce que vous faites des quiz? Tu le fais bien? ?? Et en parlant de quiz, après tout Hana est un quiz rapide! Je pense que tout le monde travaille en ligne et hors ligne de différentes manières chaque jour pour des quiz rapides.

Au fait, lorsque vous faites un quiz rapide, cela vous inquiète peut-être, non?

Si vous êtes un joueur de quiz, vous aurez ce genre de question une fois, non? ~~ Teka, tiens moi ☆ ~~ Le but et le but de cet article est de répondre de front à ces questions avec des méthodes techniques et mathématiques **.

Au fait, le code source et les formules sont désormais foirés dans cet article. Bien sûr, vous pouvez omettre tout cela et écrire une conclusion soudainement, mais je veux dire un peu "c'est ressemblance" ~~ Je suis le roi du Secret Lab Center ou le conférencier de la soirée de fin d'études ~~ Parce que c'est aussi un engagement de (putain de gênant), j'ose écrire une description compliquée. Bien sûr, nous essaierons d'expliquer les parties essentielles du quiz lui-même aussi simplement que possible, mais comprenez bien que nous omettons les explications détaillées des parties spécialisées (en particulier les aspects techniques). Quoi qu'il en soit, ** Si vous ne comprenez pas, sautez-le et lisez-le **.

En outre, juste au cas où le code de programme affiché ici n'a pas été confirmé pour fonctionner correctement, il peut donc provoquer des problèmes inattendus. L'auteur n'est pas responsable de tels problèmes, veuillez donc l'utiliser à vos propres risques. De plus, les résultats et les discussions ne sont que mes impressions personnelles, alors ne les prenez pas trop.

Passons à l'entrée du ** Quiz Statistics ** académique.

** [Note] ** Ici, suivez les étapes ci-dessous pour organiser les données des questions du quiz dans le flux HTML → base de données SQL → fichier CSV, mais bien sûr, omettez la base de données SQL et HTML → fichier CSV, Mais il n'y a aucun problème. En d'autres termes, vous n'avez même pas besoin d'écrire un programme séparé et vous pouvez bien copier du HTML dans Excel, etc., ce qui est mieux compte tenu de l'efficacité du travail. La description suivante est

―― D'une manière ou d'une autre, il semble qu'il est plus facile de jouer et de s'organiser de différentes manières si vous le mettez une fois dans la base de données. ――Je ne suis pas très doué pour utiliser Excel personnellement, je veux donc le faire d'une manière qui n'utilise pas Excel autant que possible.

C'est à cause de circonstances personnelles et de circonstances, donc si vous dites que vous n'avez pas besoin d'une base de données, c'est vrai, et si vous dites qu'Excel est suffisant, c'est vrai. ** Après cela, il ne s'agit que d'un enregistrement de ce que j'ai essayé car j'ai peu d'historique d'activités de quiz, alors sachez qu'il y a essentiellement des parties et des détours redondants. ** **

Préparation des données de questions de quiz à analyser

Extraction de phrases de questions et de réponses et stockage dans la base de données

En passant, nous analyserons les phrases des questions de quiz à partir d'ici, mais bien sûr, cela ne commencera pas à moins qu'il n'y ait une question de quiz à analyser. Cette fois, parmi les questions de quiz publiées par Quiz no Mori, seules les questions de la "série abc", qui semble être la phrase de question de quiz la plus standard, A été utilisé.

La question du quiz est publiée au format HTML, mais elle est un peu difficile à gérer telle quelle, je vais donc commencer par extraire proprement la phrase de la question et la réponse de ce fichier HTML. Soit dit en passant, plongons dans la base de données pour une utilisation plus facile plus tard.

Problème avec abc Après avoir sauvegardé tous les fichiers HTML dans le répertoire ʻabcquiz, unifiez d'abord le code de caractère des fichiers HTML en UTF-8. Si vous avez enregistré tous les fichiers HTML dans le répertoire ʻabcquiz, vous pouvez convertir par lots le code de caractère avec la commande suivante.

nkf -w --overwrite ./abcquiz/*.htm

Une fois la conversion du code de caractère terminée, écrivez un script Python et exécutez-le. Ici, les packages MySQLdb et bs4 utilisés dans le script Python ci-dessous ne sont pas inclus par défaut, vous devez donc les installer séparément. Par exemple, si vous utilisez la commande pip, vous pouvez l'installer comme ceci.

sudo pip install MySQL-python
sudo pip install beautifulsoup4

Exécutez ensuite le programme Python suivant. Les scripts Python suivants sont basés sur l'hypothèse qu'ils fonctionneront avec Python 2.x.

extract_abcquiz_into_mysqldb.py


# coding: utf-8

import os
import re
import codecs
import MySQLdb
from bs4 import BeautifulSoup

#Objets pour les opérations MySQL
connector = MySQLdb.connect(host="localhost", db="quiz", user="(Nom d'utilisateur)", passwd="(mot de passe)", charset="utf8")
cursor = connector.cursor()

#Rechercher tous les noms de fichiers HTML dans le dossier spécifié
file_names = os.listdir("./abcquiz/")
#Si l'instruction for entraîne la suppression de son propre élément, utilisez une copie de toutes les tranches.
for f in file_names[:]:
    if ".htm" not in f:
        file_names.remove(f)

#Extraire et lire l'énoncé du problème (déjà en type unicode)
for f in file_names:
    open_file = codecs.open("./abcquiz/" + f, "r", "utf8")
    whole_soup = BeautifulSoup(open_file)
    #Commencez par diviser la soupe pour chaque problème
    each_quiz_soups = whole_soup.find_all("tr")
    for qs in each_quiz_soups:
        current_quiz = {"question":u"", "answer":u""}
        #Extraire davantage les balises td
        tds = qs.find_all("td")
        is_next_of_question = False
        for td in tds:
            #La cellule td se terminant par "?" Est une déclaration de problème, alors extrayez-la.
            if re.match(ur".*\?$", td.text):
                current_quiz["question"] = td.text
                is_next_of_question = True
                continue
            #La cellule td à côté de la phrase de question est la réponse
            if is_next_of_question:
                current_quiz["answer"] = td.text
                break
        sql_query = u"insert into abcquiz (question, answer) values ('" + current_quiz["question"] + u"', '" + current_quiz["answer"] + u"')"
        try:
            cursor.execute(sql_query)
        except:
            continue

connector.commit()
cursor.close()
connector.close()

Cela extraira toutes les paires de questions et réponses du fichier HTML et les stockera dans la table abcquiz` de la base de données quiz '' avec les colonnes question et réponses`. Vous devez installer MySQL, préparer un compte utilisateur MySQL et créer au préalable la base de données quiz et la table ```abcquiz``.

Ceci complète pour le moment la base de données de 11184 questions quiz.

Exporter au format de fichier CSV

Il est un peu difficile à analyser tant qu'il est dans la base de données, alors formatez les quiz une fois stockés dans un formulaire facile à analyser et supprimez-les. J'utilise souvent le format de fichier CSV dans de tels cas, donc cette fois je vais l'exporter au format de fichier CSV. Bien sûr, il n'est pas nécessaire que ce soit CSV, mais JSON peut être utilisé.

Tout d'abord, connectez-vous à MySQL.

mysql -u (Nom d'utilisateur) -p

Après avoir saisi le mot de passe et connecté, accédez à la base de données quiz '' et exportez le contenu de la table abcquiz '' dans un fichier CSV.

use quiz;
select * from abcquiz into outfile 'abcquiz.csv' fields terminated by ',';

Si vous essayez de générer un fichier CSV, vous pouvez obtenir une erreur telle que secure-file-priv '' et cela peut ne pas fonctionner. Ces solutions sont au cas par cas et seront longues à exporter, donc je les omettrai ici, mais il semble qu'il y ait de nombreux cas où la valeur de secure-file-priv`` est NULL, donc " Si vous traitez avec la direction de "décidez simplement de la valeur de" secure_file_priv "dans le" my.cnf "chargé, cela fonctionnera probablement.

(Référence) Mysql rendant l'option --secure-file-priv à NULL --Stack Overflow http://stackoverflow.com/questions/37543177/mysql-making-secure-file-priv-option-to-null

Par le processus jusqu'à présent, le fichier CSV suivant, c'est-à-dire un fichier texte de 11 184 lignes dans lequel la phrase de question et la réponse sont séparées par une virgule demi-largeur, est généré.

L'élément du symbole d'élément B est le bore, mais quel est l'élément du symbole d'élément C?,carbone
Quel genre de larmes pensez-vous d'un petit salaire ou de partager comme un oiseau?,Larmes d'un moineau
Le premier général du shogunat de Kamakura est Genryocho, mais qui est le premier général du shogunat de Muromachi?,Takauji Ashikaga
Qui est l'actuel entraîneur de l'équipe nationale de football du Japon, surnommée "Skinny"?,Ziko
Quelle couleur est utilisée pour le drapeau américain mais pas pour le drapeau japonais?,Bleu
・
・
・

En utilisant cela comme un matériau, nous analyserons en fait diverses choses dans le prochain chapitre.

Analyse des problèmes par correspondance de modèles

Faisons une petite analyse. Voici l'une des questions que le joueur quiz a évoquées au début de l'article

Je vais vous donner la réponse. Ici, les définitions du problème parallèle et du problème de la source de mots sont les suivantes.

Maintenant, créons un programme qui lit le fichier CSV généré précédemment, compte le nombre de problèmes correspondant à ces modèles et calcule le rapport d'apparence à l'ensemble.

count_parallel_gogen_question.py


# coding: utf-8

import csv
import re

#Lire l'énoncé du problème à partir du fichier CSV créé à l'avance (première colonne du CSV)
questions = []
with open("./abcquiz.csv", "r") as f:
    reader = csv.reader(f)
    for row in reader:
        questions.append(row[0].decode("utf8"))

#Spécifiez le modèle de chaîne de caractères à rechercher avec une expression régulière
parallel_pattern = re.compile(ur"mais")
gogen_pattern = re.compile(ur"Dans les mots.*veux dire")

#Comptez le nombre de questions qui correspondent au modèle spécifié
parallel_num = 0
gogen_num = 0
for q in questions:
    if re.search(parallel_pattern, q):
        parallel_num += 1
    if re.search(gogen_pattern, q):
        gogen_num += 1

#Calculez le rapport d'apparence en fonction du résultat du comptage
parallel_probability = float(parallel_num) / float(len(questions))
gogen_probability = float(gogen_num) / float(len(questions))

#Sortie de résultat
print u"Nombre total de problèmes= ", unicode(len(questions))
print u"Nombre de problèmes parallèles= ", unicode(parallel_num), u"(Rapport de questions= ", u"{:.2f}".format(parallel_probability * 100.0), u"%,", u"{:.2f}".format(1.0 / parallel_probability), u"1 question par question)"
print u"Nombre de problèmes de source de mots= ", unicode(gogen_num), u"(Rapport de questions= ", u"{:.2f}".format(gogen_probability * 100.0), u"%,", u"{:.2f}".format(1.0 / gogen_probability), u"1 question par question)"

Lorsque vous exécutez ce gars, vous verrez ce résultat à l'écran.

Nombre total de problèmes=  11184
Nombre de problèmes parallèles=1083 (Rapport de questions=  9.68 %, 10.1 sur 33 questions)
Nombre de problèmes de source de mots=244 (Rapport de questions=  2.18 %, 45.1 questions sur 84)

Oui, vous avez la réponse à votre question!

Au cas où, vérifions si nous pouvons bien saisir le problème parallèle et le problème de la source des mots. À l'endroit où le problème parallèle est compté dans le code précédent, ajoutez une ligne d'instruction `` print '' qui affiche l'énoncé de problème à l'écran.

    if re.search(parallel_pattern, q):
        parallel_num += 1
        print q

Ensuite, les phrases de problème jugées comme des problèmes parallèles seront affichées sur l'écran dans une rangée, alors jetons un coup d'œil.

L'élément du symbole d'élément B est le bore, mais quel est l'élément du symbole d'élément C?
Le premier général du shogunat de Kamakura est Genryocho, mais qui est le premier général du shogunat de Muromachi?
Le surnom de l'Akita Shinkansen est "Komachi", mais quel est le surnom du Yamagata Shinkansen?
Un autre nom pour le sport est le hockey sur glace, qui s'appelle «combats sur glace», mais qu'est-ce que l'on appelle «échecs sur glace»?
Le plus gros poisson du monde est le requin, mais quel est le plus gros amphibien du monde?
・
・
・

Comme vous vous en doutez, des problèmes parallèles ont été détectés et comptés. De plus, si vous regardez cette liste tout le temps, vous verrez l'énoncé de problème suivant sur le chemin.

Negi appartient à la famille des lys et le gingembre appartient à la famille du gingembre, mais quel genre de wasabi s'agit-il?

C'est un soi-disant «problème à trois para» dans lequel deux éléments apparaissent avant «mais» et le troisième élément apparaît. Dans la définition du problème parallèle cette fois, ces problèmes à trois para sont également pris en compte. Si vous concevez une définition, vous ne pouvez extraire que le problème 3-para.

De même, vérifions le problème de l'origine des mots. Je vais déplacer la phrase `` imprimer '' que j'ai ajoutée plus tôt à l'endroit où le problème d'origine du mot est compté.

    if re.search(gogen_pattern, q):
        gogen_num += 1
        print q

Et exécutez.

Qu'est-ce qu'un gâteau qui imite littéralement un arbre annuel, ce qui signifie «gâteau en bois» en allemand?
Quel est le mouvement des chrétiens pour reprendre la péninsule ibérique occupée par les musulmans, ce qui signifie «reconquérir» en espagnol?
Quel est le style stand-up lors des fêtes, ce qui signifie «armoire à vaisselle» en français?
Quelle est la politique de l'ex-Union soviétique pour développer une politique et une économie ouvertes, ce qui signifie «divulgation d'informations» en russe?
Qu'est-ce qu'un dessert froid et sucré qui signifie «parfait» en français et qui contient une variété de fruits, de chocolats et plus encore?
・
・
・

Ouais, c'est aussi bien! Cela semble aller. Si vous regardez la liste, vous trouverez des phrases problématiques avec des couleurs de cheveux légèrement différentes.

Quel est le matériel agricole qui a le nom «combiné» en anglais parce qu'il peut être coupé et grainé à la fois?
Qu'est-ce qu'une confiserie occidentale faite en saupoudrant de chocolat sur un chou à la crème allongé dont le nom signifie «éclair» en français?

C'est un modèle dans lequel l'expression «signifiant □□ en ◯◯ langage» apparaît au milieu. Ici, connaître l'origine peut ne pas être un grand avantage (par exemple, les problèmes énumérés ci-dessus peuvent être poussés devant eux même s'ils ne connaissent pas le sens de l'anglais ou du français. Je pense que c'est un problème), donc il peut être un peu faible de l'appeler un soi-disant "problème de source de mots".

En outre, une déclaration de problème sous une forme légèrement inattendue a été détectée.

Quel est le mot traduit par "Confidencial" en anglais, qui signifie accompagner la lettre et ne la lire que par le destinataire?

Ce problème, le modèle de «signification (chaîne de caractères arbitraires) dans les mots», qui est la définition du problème de source de mots défini cette fois, est certainement inclus. Cependant, en tant que forme pratique, la traduction dans d'autres langues apparaît au début, donc ce n'est peut-être pas un problème d'origine. Eh bien, cette fois, je voulais juste avoir une idée approximative du rapport des questions, donc cette question n'affecte pas la majorité des résultats, mais si vous voulez une analyse plus détaillée, vous devrez la considérer.

en conclusion

Donc, dans cet article, j'ai repris les questions passées de la série abc comme sujet, leur traitement technique, les résultats réels de l'analyse et leur examen. Par conséquent,

Cependant, cette fois, nous ne traitons que des problèmes de la série abc il y a environ 10 ans, de sorte que dans la tendance récente aux questionnaires, ce rapport peut avoir considérablement changé. Je peux y penser.

Eh bien, au début j'ai mentionné une question du joueur de quiz, mais en plus de la question qui vient d'être résolue, il y avait une autre question, non?

En fait, le sujet de la résolution de cette question était le sujet principal, mais l'article semble être un peu long, donc aujourd'hui je vais le décomposer ici, et un autre jour comme "Quiz Statistics (2)" J'aimerais le publier à nouveau. Je pense que l'analyse effectuée dans cet article est assez possible avec la fonction `` COUNTIF '' d'Excel tant qu'il y a des données de phrase problématiques, mais la prochaine fois, cela ne pourra pas être résolu sans utiliser des méthodes de programmation spécialisées. Nous prévoyons de traiter de tels contenus avec fermeté. Si cela ne vous dérange pas, s'il vous plaît, sortez avec moi à nouveau.

Je tiens à exprimer ma sincère gratitude à tous ceux qui ont lu jusqu'ici et ont conclu "Quiz Statistics (1)". Rendez-vous à nouveau dans "Quiz Statistics (2)".

Recommended Posts

Introduction aux statistiques de quiz (1) -Analyse mathématique des phrases de questions pour connaître la tendance des questions-
[Python] PCA scratch dans l'exemple de "Introduction à la méthode d'analyse multivariée"
De l'introduction de JUMAN ++ à l'analyse morphologique du japonais avec Python
Introduction à la modélisation statistique pour l'analyse des données Élargissement de la gamme d'applications de GLM
Une introduction à l'analyse de données à l'aide de Python - Pour augmenter le nombre de vues vidéo -
De l'introduction de pyethapp à l'exécution du contrat
[Introduction à Python] Utilisation basique de la bibliothèque scipy que vous devez absolument connaître
Comment connaître le numéro de port du service xinetd
Compréhension mathématique de l'analyse en composantes principales depuis le début
[Introduction à Python] Utilisation basique de la bibliothèque matplotlib
[Introduction aux Data Scientists] Statistiques descriptives et analyse de régression simple ♬
Une introduction à l'orientation des objets - changeons l'état interne d'un objet
Je veux connaître la nature de Python et pip
Je veux connaître la légende du monde des technologies informatiques