[PYTHON] Extrayons automatiquement les informations des employés telles que le salaire moyen des données XBRL divulguées par EDINET (5/10)

Dans le 5ème article du Calendrier de l'Avent, j'essaierai d'extraire les informations souhaitées des données XBRL acquises par l'API EDINET. Cette fois, j'ai essayé de cibler le salaire moyen et l'âge moyen des entreprises que l'on voit souvent dans la recherche d'emploi.

(Le programme de cet article est fourni tel quel sans aucune garantie, et XBRL Japan assumera toute la responsabilité de tous les inconvénients ou problèmes pouvant survenir à la suite de l'utilisation de ce programme, quelle qu'en soit la cause. Je ne le supporterai pas.)

1. Extraire des informations spécifiques des données XBRL

1.1 Aperçu du programme

Il s'agit d'un programme en langage Python qui décompresse et analyse le fichier zip (y compris les données XBRL) acquis par l'API EDINET, extrait des informations telles que le salaire du rapport sur les titres, puis génère les informations nécessaires sous forme de CSV. (Tous les codes sont répertoriés dans "3. Code source") Les éléments à extraire des données XBRL sont indiqués dans le tableau ci-dessous.

article                                        Nom d'élément défini dans XBRL                                                     Exemple d'acquisition                                    
EDINETCODE EDINETCodeDEI E00004
Nom de la compagnie FilerNameInJapaneseDEI Kaneko Seedling Co., Ltd.
Salaire annuel moyen (yen) AverageAnnualSalaryInformationAboutReportingCompanyInformationAboutEmployees 5,554,933
Années de service moyennes (années) AverageLengthOfServiceYearsInformationAboutReportingCompanyInformationAboutEmployees 13.0
Années de service moyennes (mois) AverageLengthOfServiceMonthsInformationAboutReportingCompanyInformationAboutEmployees -
Âge moyen (années) AverageAgeYearsInformationAboutReportingCompanyInformationAboutEmployees 42.2
Âge moyen (mois) AverageAgeMonthsInformationAboutReportingCompanyInformationAboutEmployees -
Nombre d'employés (personnes) NumberOfEmployees 625

D'autres points caractéristiques sont décrits ci-dessous. ○ Utilisez la liste de codes EDINET pour identifier le «secteur» de l'entreprise ○ Il ne correspond pas à l'acquisition du «poste d'extension unique» de la société ○ Un analyseur OSS appelé «Arelle» a été utilisé pour l'analyse XBRL. ○ S'il existe une ancienneté moyenne (mois) et un âge moyen (mois), «conversion annuelle» (arrondie à la deuxième décimale).

1.2 Préparation

Veuillez prendre les mesures suivantes avant d'exécuter le programme. De plus, il est nécessaire d'installer au préalable d'autres bibliothèques. En fonction de l'environnement d'exécution, modifiez la méthode de codage et de spécification de chemin selon le cas.

1.2.1 Préparation des données XBRL

Utilisez "Trouvons les données décrites dans XBRL", "Collectons les données décrites dans XBRL", etc. pour télécharger le fichier zip (y compris les données XBRL) depuis EDINET. Le salaire annuel moyen (yen) et les autres éléments sont des éléments nouvellement ajoutés sur EDINET, donc pour le moment, 2019 Téléchargez les données XBRL divulguées après le 1er avril.

1.2.2 Installation de l'analyseur XBRL

Installez l'analyseur XBRL appelé Arelle. Lorsque ʻArelle` charge une instance, il analyse l'ensemble DTS, y compris les informations de taxonomie externe. Par conséquent, il convient à l'utilisation de données XBRL avancées, mais si vous n'utilisez que des instances, son traitement prend du temps, pensez donc à le remplacer par la bibliothèque XML OSS ou l'analyseur que vous développez. ..

L'article qiita contient également des informations sur la façon d'installer Arelle et d'autres analyseurs en cours de développement, je vais donc en énumérer quelques-uns ici. ・ Analyse XBRL qui ne part pas de zéro (utilisation d'Arelle)

1.2.3 Préparation de la liste de codes EDINET

Il peut être téléchargé à partir de la «liste de codes EDINET» au bas de la page après la transition de l'onglet [Télécharger] du site EDINET. Cette liste est répertoriée avec ʻEDINET CODE et l'industrie. Par conséquent, en utilisant cette liste, vous pouvez également acquérir le type d'entreprise de l'entreprise. スクリーンショット 2019-12-01 20.34.47.png

1.2.4 Détermination du dossier de stockage / décompression / sortie

○ Choisissez un dossier de stockage pour lire la liste de codes EDINET téléchargée. edinetcodedlinfo_filepath = 'C://Users//xxx//Desktop//xbrlReport//EdinetcodeDlInfo.csv'

○ Décidons du dossier pour stocker le fichier zip acquis par l'API EDINET. zip_dir = 'C://Users//xxx//Desktop//xbrlReport//SR//'

○ Choisissez le dossier et le nom de fichier pour la sortie CSV. employee_frame.to_csv("C://Users//xxx//Desktop//xbrlReport//xbrl_qiita.csv", encoding='cp932')

1.3 Résultat de l'exécution

Décompressez le fichier zip obtenu par l'API EDINET et récupérez la liste des «fichiers d'instance» (extension .xbrl) sous le dossier PublicDoc placé avec «glob». (L'explication du processus par décompression zip est omise)

Code1


xbrl_file_expressions = glob.glob('C:\\Users\\xxx\\Desktop\\xbrlReport\\SR\\XBRL\\PublicDoc\\*.xbrl')

Result1


['C:\\Users\\XXX\\Desktop\\xbrlReport\\SR\\XBRL\\PublicDoc\\jpcrp030000-asr-001_E00112-000_2019-03-31_01_2019-06-27.xbrl', 'C:\\Users\\XXX\\Desktop\\xbrlReport\\SR\\XBRL\\PublicDoc\\jpcrp030000-asr-001_E01422-000_2019-03-31_01_2019-06-27.xbrl', 'C:\\Users\\XXX\\Desktop\\xbrlReport\\SR\\XBRL\\PublicDoc\\jpcrp030000-asr-001_E02770-000_2019-03-31_01_2019-06-21.xbrl', 'C:\\Users\\XXX\\Desktop\\xbrlReport\\SR\\XBRL\\PublicDoc\\jpcrp030000-asr-001_E04510-000_2019-03-31_01_2019-06-27.xbrl']

Le traitement en boucle est effectué à l'aide de xbrl_files, et les données XBRL sont lues par le modelManager.load (xbrl_file) d'Arelle pour chaque fichier d'instance. En conséquence, vous pouvez obtenir l'objet model_xbrl d'Arelle qui contient les informations de données XBRL.

Code2


 for index, xbrl_file in enumerate(xbrl_files):

    ctrl = Cntlr.Cntlr()
    model_manager= ModelManager.initialize(ctrl)
    model_xbrl= modelManager.load(xbrl_file)

Result2



<arelle.ModelXbrl.Model_xbrl object at 0x0EF6F350>

Ensuite, le traitement en boucle est effectué à l'aide de model_xbrl.facts, dans lequel tous les faits (les données réelles telles que les valeurs numériques des éléments) contenues dans l'instance sont définis au format liste, et le nom d'élément de chaque fait ( fact. get concept.qname.localName). Lorsque le nom de l'élément est le nom de l'élément à extraire cette fois, c'est un mécanisme pour acquérir la valeur numérique («fact.value») de l'élément. Lors du traitement de EDINETCODE, incorporer la logique permettant d'identifier le secteur d'activité de l'entreprise à partir de ʻEdinetcodeDlInfo.csv. En ce qui concerne le nombre d'employés, comme le même nom d'élément existe plusieurs fois, la période courante (CurrentYearInstant) est spécifiée dans l'attribut de période appelé context`.

Code3


for fact in model_xbrl.facts:
    if fact.concept.qname.localName == 'EDINETCodeDEI':
        edinet_code = fact.value

        for code_name in edinet_info_list:
            if code_name[0] == edinet_code:
                industry_code = code_name[1]
                break

 elif fact.concept.qname.localName=='FilerNameInJapaneseDEI':
 elif fact.concept.qname.localName=='AverageAnnualSalaryInformationAboutReportingCompanyInformationAboutEmployees':
 elif fact.concept.qname.localName=='AverageLengthOfServiceYearsInformationAboutReportingCompanyInformationAboutEmployees':
 elif fact.concept.qname.localName=='AverageLengthOfServiceMonthsInformationAboutReportingCompanyInformationAboutEmployees':
 elif fact.concept.qname.localName=='AverageAgeYearsInformationAboutReportingCompanyInformationAboutEmployees':
 elif fact.concept.qname.localName=='AverageAgeMonthsInformationAboutReportingCompanyInformationAboutEmployees':
 elif fact.concept.qname.localName=='NumberOfEmployees':
     if fact.contextID == 'CurrentYearInstant_NonConsolidatedMember':

Après cela, les informations de chaque élément acquis (ʻedinet_code, filer_name_jp, ʻindustry_code, salaire_info, service_years, ʻage_years, number_of_employees) sont stockées dans company_info_list. À l'heure actuelle, si les années moyennes de service (mois) (service_months) et l'âge moyen (mois) (ʻage_months) existent, nous avons incorporé un processus pour les convertir en années. Après cela, si vous stockez company_info_list dans l'unité EDINETCODE (unité de fichier d'instance) dans ʻedinet_company_info_list`, une liste contenant les informations des employés de chaque entreprise sera complétée.

Code4


    company_info_list.append(edinet_code)
    company_info_list.append(filer_name_jp)
    company_info_list.append(industry_code)
    company_info_list.append(salary_info)

    if len(service_months) != 0:
        service_years_decimal= round(int(service_months)/12,1)
        service_years = int(service_years) + service_years_decimal
        service_years = str(service_years)

    company_info_list.append(service_years)

    if len(age_months) != 0:
        age_years_decimal= round(int(age_months)/12,1)
        age_years = int(age_years) + age_years_decimal
        age_years = str(age_years)

    company_info_list.append(age_years)
    company_info_list.append(number_of_employees)

    edinet_company_info_list.append(Company_info_list)

ʻEdinet_company_info_list` ressemble à ceci:

Result4


[['E00112', 'Totetsu Kogyo Co., Ltd.', 'Industrie de construction', '8547489', '13.8', '41.2', '1673'], ['E01422', 'Fuji Sash Co., Ltd.', 'Produits métalliques', '5527000', '20.7', '44.7', '850'], ['E02770', 'Siège social du groupe Misumi', 'Commerce de gros', '', '', '', '1293'], ['E04510', 'Power Development Co., Ltd.', 'Industrie de l'électricité et du gaz', '7980312', '19.6', '40.9', '2445']・ ・ ・]

Enfin, la ʻedinet_company_info_list` acquise est sortie au format CSV. Ceci termine l'extraction des éléments requis.

Code5


employee_frame = pd.DataFrame(edinet_company_info_list,
                         columns=['EDINETCODE', 'Nom de la compagnie', 'Industrie', 'Salaire annuel moyen (yen)', 'Années de service moyennes (années)', 'Âge moyen (années)', 'Nombre d'employés (personnes)'])
employee_frame.to_csv("C://Users//xxx//Desktop//xbrlReport//xbrl_qiita.csv", encoding='cp932')

En passant, lorsque vous exécutez le programme, le fichier CSV suivant sera généré à la fin. Il existe plusieurs types d'unités salariales annuelles moyennes (yens, 1 000 yens, etc.) selon la méthode de divulgation de l'entreprise. De plus, bien que nous ciblions les données à partir d'avril 2019, en raison de la fin de l'exercice de chaque entreprise, certaines n'ont pas encore été balisées et les données relatives aux salaires ne peuvent pas être obtenues.

2. Code source


# -*- coding: utf-8 -*-

from arelle import ModelManager
from arelle import Cntlr
import os
import zipfile
import glob
import pandas as pd


def make_edinet_info_list(edinetcodedlinfo_filepath):
    edinet_info = pd.read_csv(edinetcodedlinfo_filepath, skiprows=1,
                                 encoding='cp932')
    edinet_info = edinet_info[["Code EDINET", "Industrie des soumissionnaires"]]
    edinet_info_list = edinet_info.values.tolist()
    return edinet_info_list

def unzip_file(zip_dir,xbrl_file_expressions):
    zip_files = glob.glob(os.path.join(zip_dir, '*.zip'))

    number_of_zip_lists = len(zip_files)
    print("number_of_zip_lists:", number_of_zip_lists)

    for index, zip_file in enumerate(zip_files):
        print(zip_file, ":", index + 1, "/", number_of_zip_lists)
        with zipfile.ZipFile(zip_file) as zip_f:
            zip_f.extractall(zip_dir)
            zip_f.close()

    xbrl_files = glob.glob(xbrl_file_expressions)
    return xbrl_files

def make_edinet_company_info_list(xbrl_files,edinet_info_list):
    edinet_company_info_list = []
    for index, xbrl_file in enumerate(xbrl_files):
        edinet_code = ""  # EDINETCODE
        filer_name_jp = ""  #Nom de la compagnie
        industry_code = ""  #Industrie
        salary_info = ""  #Salaire annuel moyen (yen)
        service_years = ""  #Années de service moyennes (années)
        service_months = ""  #Années de service moyennes (mois)
        age_years = ""  #Âge moyen (années)
        age_months = ""  #Âge moyen (mois)
        number_of_employees = ""  #Nombre d'employés (personnes)
        company_info_list = []  #Information d'entreprise

        ctrl = Cntlr.Cntlr()
        model_manager = ModelManager.initialize(ctrl)
        model_xbrl = model_manager.load(xbrl_file)

        print(xbrl_file, ":", index + 1, "/", len(xbrl_files))

        for fact in model_xbrl.facts:

            if fact.concept.qname.localName == 'EDINETCodeDEI':
                print("Code EDINET", fact.value)
                edinet_code = fact.value

                for code_name in edinet_info_list:
                    if code_name[0] == edinet_code:
                        print("Industrie",code_name[1])
                        industry_code = code_name[1]
                        break

            elif fact.concept.qname.localName == 'FilerNameInJapaneseDEI':
                print("Nom de la compagnie", fact.value)
                filer_name_jp = fact.value

            elif fact.concept.qname.localName == 'AverageAnnualSalaryInformationAboutReportingCompanyInformationAboutEmployees':
                print("Salaire annuel moyen (yen)", fact.value)
                salary_info = fact.value

            elif fact.concept.qname.localName == 'AverageLengthOfServiceYearsInformationAboutReportingCompanyInformationAboutEmployees':
                print("Années de service moyennes (années)", fact.value)
                service_years = fact.value

            elif fact.concept.qname.localName == 'AverageLengthOfServiceMonthsInformationAboutReportingCompanyInformationAboutEmployees':
                print("Années de service moyennes (mois)", fact.value)
                service_months = fact.value

            elif fact.concept.qname.localName == 'AverageAgeYearsInformationAboutReportingCompanyInformationAboutEmployees':
                print("Âge moyen (années)", fact.value)
                age_years = fact.value

            elif fact.concept.qname.localName == 'AverageAgeMonthsInformationAboutReportingCompanyInformationAboutEmployees':
                print("Âge moyen (mois)", fact.value)
                age_months = fact.value

            elif fact.concept.qname.localName == 'NumberOfEmployees':
                if fact.contextID == 'CurrentYearInstant_NonConsolidatedMember':
                    print("Nombre d'employés (personnes)", fact.value)
                    number_of_employees = fact.value

        print("")
        company_info_list.append(edinet_code)
        company_info_list.append(filer_name_jp)
        company_info_list.append(industry_code)
        company_info_list.append(salary_info)

        if len(service_months) != 0:
            service_years_decimal = round(int(service_months) / 12, 1)
            service_years = int(service_years) + service_years_decimal
            service_years = str(service_years)

        company_info_list.append(service_years)

        if len(age_months) != 0:
            age_years_decimal = round(int(age_months) / 12, 1)
            age_years = int(age_years) + age_years_decimal
            age_years = str(age_years)

        company_info_list.append(age_years)
        company_info_list.append(number_of_employees)

        edinet_company_info_list.append(company_info_list)

    return edinet_company_info_list

def write_csv_of_employee_info(edinet_company_info_list):

    employee_frame = pd.DataFrame(edinet_company_info_list,
                         columns=['EDINETCODE', 'Nom de la compagnie', 'Industrie', 'Salaire annuel moyen (yen)', 'Années de service moyennes (années)', 'Âge moyen (années)', 'Nombre d'employés (personnes)'])

    print(employee_frame)
    employee_frame.to_csv("C://Users//xxx//Desktop//xbrlReport//xbrl_qiita.csv", encoding='cp932')


def main():
    edinetcodedlinfo_filepath = 'C://Users//xxx//Desktop//xbrlReport//EdinetcodeDlInfo.csv'
    edinet_info_list = make_edinet_info_list(edinetcodedlinfo_filepath)

    zip_dir = 'C://Users//xxx//Desktop//xbrlReport//SR//'
    xbrl_file_expressions = 'C://Users//xxx//Desktop//xbrlReport//SR//XBRL//PublicDoc//*.xbrl'
    xbrl_files = unzip_file(zip_dir,xbrl_file_expressions)

    edinet_company_info_list = make_edinet_company_info_list(xbrl_files,edinet_info_list)
    print(edinet_company_info_list)

    write_csv_of_employee_info(edinet_company_info_list)
    print("extract finish")

if __name__ == "__main__":
    main()


3. Comment extraire des informations autres que les informations sur les employés

Le nom de l'élément défini dans XBRL (ex.EDINETCodeDEI) a été décrit sans explication particulière, mais tous sont publiés sur le site EDINET. La dernière version en décembre 2019 est la liste des éléments de la taxonomie et la liste des comptes de À propos de la publication de la taxonomie EDINET 2020. Vous pouvez vérifier à partir de . Les sujets extraits cette fois sont listés dans la liste des éléments de taxonomie (1e_ElementList.xlsx`). Pour plus de détails, voir [Ordonnance n ° 3 du Cabinet Office sur les valeurs mobilières, rapport sur la divulgation des détails de l'entreprise, etc. (jpcrp030000-asr)] - [9] Feuille --212000b Statut de l'employé (jpcrp_212000-002_2019-11-01_pre.xml) ), Vérifiez s'il vous plaît. En utilisant ces listes, il est possible d'extraire divers sujets autres que les informations sur les employés. La taxonomie EDINET peut être mise à jour afin de répondre à la révision des lois et des normes comptables. Par conséquent, avant de traiter une instance, assurez-vous que la version de la taxonomie EDINET est correcte.

4. Coordonnées

Pour toute demande concernant cet article, veuillez contacter l'adresse e-mail suivante. e-mail:[email protected] (Bien sûr, les commentaires sur qiita sont également les bienvenus)

Cette adresse e-mail sera le point de contact pour les demandes de renseignements sur le Comité de développement de XBRL Japan, qui rédige l'article sur qiita. Je vais. Par conséquent, nous ne pouvons pas répondre aux demandes générales sur l'organisation en fonction du contenu, mais n'hésitez pas à nous contacter pour toutes questions techniques, opinions, demandes, conseils, etc. concernant XBRL. Veuillez noter que la réponse peut prendre un certain temps car les membres du comité sont des bénévoles.

Recommended Posts

Extrayons automatiquement les informations des employés telles que le salaire moyen des données XBRL divulguées par EDINET (5/10)
Visualisons la relation entre le salaire moyen et l'industrie avec des données XBRL et seaborn! (7/10)
Définir des informations telles que la longueur sur le bord de NetworkX
Extraction d'informations à partir du fichier EDINET XBRL