RでEDINETから財務データを入手・分析する~⑥前処理編3/3~
記事一覧
はじめに
本記事は前処理編2/3の続きであり、6番目の記事にあたる。本記事で行う作業は、前2記事の内容を統合した関数を定義し、実際にzipファイルを分析可能なデータへと整頓することである。
また、本ブログの執筆に際してこちらの記事を参考にさせていただいた。
考慮事項
詳細な流れはRによる実装の手順に回し、ここでは分析にあたって考慮すべき事項、説明すべき事項を挙げる。
labelStringについて
前記事で、xbrlDoAll()
の処理は1分程度かかるとした。筆者の試行錯誤の結果、処理時間のボトルネックはxbrlProcessLabels()
だと特定した。この関数は前処理編1/3で実行済みのため、処理速度の改善が行えた。
会計基準について
導入編で挙げた通り、本ブログでは日本基準を採用する上場企業のみを抽出することを考える。IFRSとUSGAAPに従う企業のデータを抽出はしないが、どの企業がそれらに従っているかをデータとして保持しておくことは有用と考えられるから、その点をカバーする。
連結財務諸表について
連結財務諸表を作成する上場企業は、有価証券報告書の中で個別と連結2つの財務諸表を報告している。よってxbrlファイル内にも、その両方の情報が混在している。一方で、上場企業には子会社を持たず、連結財務諸表を作成していない企業も存在する。それらの企業にはxbrlファイル内の個別財務諸表の情報のみしかない。
そこで、連結財務諸表を作成する企業は連結財務諸表を、そうではない企業は個別財務諸表を抽出する必要があり、その判断をしなければならない。具体的には、「個別財務諸表にあたらない行」を含む(nrow()
> 0)なら連結、そうでないなら(nrow()
== 0)個別を取得するようにする。
Rによる実装
手順
詳細な流れは以下の通りである。
for文で使いまわす情報である財務諸表名、提出日の年、labelStringを含むdata.frame(JGAAP_label_YYYY.csv)を用意する。
zipファイルを解凍し、xbrlファイルへのpathを取得する。
fact、context、採用する会計基準を取得する。
会計基準で場合分けする。メインの処理は日本基準の採用企業である。
fact、context、labelStringをjoinし、連結財務諸表作成企業であるか判断する。その後、判断に応じて適切なdefinitionとjoined_fclを統合したjoined_dataを作成する。
joined_dataに最後の調整を加える。
joined_tidy_dataのlabelStringに欠損があるか調べる*1。欠損がない場合は"docID.csv"としてtidyupフォルダに保存する。ある場合はエラーを出す。
日本基準を採用していない場合は、そのdocIDと採用する会計基準のみをもつ"**_docID.txt"として保存する。
解凍後のXBRLファイル群の削除、for文内の変数のクリーンアップを行い、進捗状況をconsoleに表示する。
2~9の内容を繰り返す。
コード
上記の手順に倣った関数を以下に与える。
tidyup_data <- function(path_zipdata, path_label, path_tidyup, start, end){ print(str_c("start!", now(), sep = ", ")) i <- as.integer(start - 1L) fs_name <- c("BalanceSheet", "StatementOfIncome", "StatementOfCashFlows", "StatementOfComprehensiveIncome", "StatementOfChangesInEquity") path_zip <- dirname(path_zipdata) %>% unique() filing_year <- path_zip %>% str_split("/", simplify = TRUE) %>% str_subset("filing$") %>% str_sub(1L, 4L) ## label label <- dir(path_label, filing_year, full.names = TRUE) %>% str_subset("\\.csv$") %>% read_csv() for(zip in path_zipdata[start:end]) { unzip(zipfile = zip, exdir = path_zip) i <- i + 1L docID <- get_docID(zip, path_zip) path_xbrl <- dir(str_c(path_zip, "/XBRL/Publicdoc"), pattern = "\\.xbrl", full.names = T) %>% str_subset("ifrs", negate = TRUE) ## fact joined_fact <- get_fact(path_xbrl) ## context joined_context <- get_context(path_xbrl) ## accounting_standard ac_standard <- get_ac_standard(joined_fact) if(ac_standard == "Japan GAAP"){ joined_fcl <- join_fcl(joined_fact, joined_context, label) ## consolidated or NOT if(is_consolidated(joined_fcl)){ ## definition joined_definition <- get_definition(path_xbrl, fs_name) %>% slice(str_which(.$roleId, "Consolidated")) joined_data <- joined_fcl %>% left_join(joined_definition, by = "elementId") %>% slice(str_which(.$elementId, "jppfs")) %>% slice(str_which(.$contextId, "NonConsolidated", negate = TRUE)) } else { ## definition joined_definition <- get_definition(path_xbrl, fs_name) %>% slice(str_which(.$roleId, "Consolidated", negate = TRUE)) # remove consolidated joined_data <- joined_fcl %>% left_join(joined_definition , by = "elementId") %>% slice(str_which(.$elementId, "jppfs")) } joined_tidy_data <- tidy_joined_data(joined_data) NA_flag <- joined_tidy_data %>% filter(is.na(labelString)) %>% nrow() if(NA_flag == 0) { # save data joined_tidy_data %>% write_excel_csv(path = str_c(path_tidyup, "/", docID, ".csv")) } else { stop(str_c("No.", i, " there are NA rows in labelString!")) } # JGAAP finished } else if(ac_standard == "IFRS"){ # save as "IFRS_**.txt" tibble( docID = docID, ac_standard = "IFRS" ) %>% write_tsv(path = str_c(path_tidyup, "/", "IFRS_", docID, ".txt")) } else if(ac_standard == "US GAAP"){ # save as "USGAAP_**.txt" tibble( docID = docID, ac_standard = "US GAAP" ) %>% write_tsv(path = str_c(path_tidyup, "/", "USGAAP_", docID, ".txt")) } ## clean up unlink(str_c(path_zip, "/XBRL"), recursive = TRUE) unlink("xbrl.Cache", recursive = TRUE) rm(list = ls(pattern = "path_xbrl|^joined|^docID$|^ac_standard$|NA_flag")) invisible(gc()) ; invisible(gc()) print(str_c(i, now(), sep = ", ")) # repeat } } tidyup_data(path_zipdata, path_label, path_tidyup, start = 1L, end = length(path_zipdata))
tidyupフォルダ内に"「企業のdocID」.csv"が保存されていれば成功である。以下にその例示を与える。
labelString | fact | startDate | endDate | elementId | contextId | roleId |
---|---|---|---|---|---|---|
現金及び預金 | 1093117000 | NA | 2018-03-31 | CashAndDeposits | Prior1YearInstant | ConsolidatedBalanceSheet |
現金及び預金 | 2184165000 | NA | 2019-03-31 | CashAndDeposits | CurrentYearInstant | ConsolidatedBalanceSheet |
受取手形及び売掛金 | 4267755000 | NA | 2018-03-31 | NotesAndAccountsReceivableTrade | Prior1YearInstant | ConsolidatedBalanceSheet |
受取手形及び売掛金 | 5012113000 | NA | 2019-03-31 | NotesAndAccountsReceivableTrade | CurrentYearInstant | ConsolidatedBalanceSheet |
電子記録債権 | 746345000 | NA | 2018-03-31 | ElectronicallyRecordedMonetaryClaimsOperatingCA | Prior1YearInstant | ConsolidatedBalanceSheet |
電子記録債権 | 992825000 | NA | 2019-03-31 | ElectronicallyRecordedMonetaryClaimsOperatingCA | CurrentYearInstant | ConsolidatedBalanceSheet |
なお、日本基準以外を採用する場合の例示は以下である。
docID | ac_standard |
---|---|
S100GBVE | IFRS |
おわりに
次回の記事では、本記事までで取得したデータに企業名や業種の情報を加えて分析する。