質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

RStudio

RStudioは、Rのプログラミングを効率化する統合開発環境です。統計計算とグラフィックスができるプログラミング言語であるRのIDEでOSSで公開されています。ソースコードやコンソールなどが一つの画面に見やすく配置されている点が特徴。コマンド名以外に、関数名やパッケージ名も補完できます。

R

R言語は、「S言語」をオープンソースとして実装なおした、統計解析向けのプログラミング言語です。 計算がとても速くグラフィックも充実しているため、数値計算に向いています。 文法的には、統計解析部分はS言語を参考にしており、データ処理部分はSchemeの影響を受けています。 世界中の専門家が開発に関わり、日々新しい手法やアルゴリズムが追加されています。

Q&A

解決済

1回答

307閲覧

Rにて、2重for構文でロングデータを作るのを高速化したい。

maltines

総合スコア12

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

RStudio

RStudioは、Rのプログラミングを効率化する統合開発環境です。統計計算とグラフィックスができるプログラミング言語であるRのIDEでOSSで公開されています。ソースコードやコンソールなどが一つの画面に見やすく配置されている点が特徴。コマンド名以外に、関数名やパッケージ名も補完できます。

R

R言語は、「S言語」をオープンソースとして実装なおした、統計解析向けのプログラミング言語です。 計算がとても速くグラフィックも充実しているため、数値計算に向いています。 文法的には、統計解析部分はS言語を参考にしており、データ処理部分はSchemeの影響を受けています。 世界中の専門家が開発に関わり、日々新しい手法やアルゴリズムが追加されています。

0グッド

0クリップ

投稿2022/12/15 05:45

編集2022/12/15 05:51

前提

以下のような約800万行4列の元データ(hyozyun)があります。

内訳は以下の通りです。
app_num: 番号
abii_name: 氏名
abii_addr: 住所
acai_app_dt: 日次

R

1head(hyozyun) 2 3app_num abii_name abii_addr acai_app_dt 42012000001 中山 明 埼玉県所沢市 20100101 52012000002 浦下 不比等 神奈川県横浜市 20100101 62012000003 高元 和人 東京都中野区 20100101 72012000004 岩澤 あや 高知県高知市 20100101 82012000009 手越 広一郎 東京都調布市 20100103 92012000009 手越 広明 東京都調布市 20100103 102012000010 市川 孝明 愛知県北名古屋市 20100104 112012000010 近藤 裕一 愛知県北名古屋市 20100104 122012000011 ウァング,ジョナサン エイ アメリカ合衆国 20100104

実現したいこと

以下のような、4列のロングデータ(名前:paneldata)を作成したいです。

pref_name: 都道府県、47種類
year:年、期間は2010/01-2021/12であるため、種類は12種類
month:月、期間は2010/01-2021/12であるため、種類は12種類
value:
元データ(hyozyun)について、以下の条件が該当する行数。
・abii_addr(住所)に、この行のpref_name(都道府県)が含まれている
・acai_app_dt(日次)に、この行のyear(年)及びmonth(月)が含まれている

イメージは以下のような感じです。
paneldata

pref_nameyearmonthvalue
北海道2010125
北海道2010237
北海道2010345
...
静岡県2017976
静岡県20171034
静岡県20171154
....

この場合ですと、行数は47都道府県×12年×12か月=6768行になります。

発生している問題、該当のソースコード

エラーは発生しておらず、動いてはいるのですが、元データ(hyozyun)が約800万行と膨大なのと、自分の知識不足により早く動くコードをかけず、何時間たっても処理が終わらない状態にあります。
遅延化している原因と改善案をご存じでしたら教えていただければ幸いです。

コードの流れは
1、データ読み込み
2、ロングデータ作成のための引数用のリストを作成
3、都道府県用リストを作成
4、表作成のための関数を作成
5、パネルデータ作成
となっています。

該当コードは以下の通りです。
コードが冗長なので、面倒な方はコード66行目の、#5 パネルデータ作成よりご覧ください。
なお、時間がかかっているのは、最後のパネルデータ作成の2重for構文です。それまでのコードは上手く迅速に処理できました。

R

1#1 データ読み込み 2 3hyozyun <- read_tsv("hyozyun.tsv", 4 locale = locale(encoding="UTF-8"), 5 show_col_types = FALSE 6 ) 7 8#2 抽出するデータの時期(年・月)のリストを作成(2010年1月-2021年12月) 9 10# 推計に使うデータの、始めと終わりの年月を指定 11SY = 2010 #開始年 12SM = 1  #開始月 13EY = 2021 #終了年 14EM = 12   #終了月 15 16T =((EY-SY+1)*12)-((SM-1)+(12-EM)) #使用するデータの総月数 17datelist_s = NULL #集計の引数用の、月始の年月日リスト準備 18datelist_e = NULL #集計の引数用の、月末の年月日リスト準備 19yearlist = NULL  #パネルデータ用の、年リスト準備 20monthlist = NULL #パネルデータ用の、月リスト準備 21 22#集計用の月始月末の年月日リスト、パネルデータ用の年リスト、月リストを作成。 23for (i in 1:T) { 24 IY = SY + floor( (i - 1) / length(TM)) 25 IM = TM[(i-1) %% length(TM) +1] 26 IDATE_s = as.character(IY*10000 + IM*100 +1 ) 27 IDATE_e = as.character(IY*10000 + IM*100 +31 ) 28 datelist_s =c(datelist_s, IDATE_s) 29 datelist_e =c(datelist_e, IDATE_e) 30 yearlist =c(yearlist, IY) 31 monthlist =c(monthlist, IM) 32} 33 34datelist_s 35>"20100101","20100201","20100301",...,"20211201" 36datelist_e 37>"20100131","20100231","20100331",...,"20211231" 38yearlist 39>2010,2010,2010,2010,2010,2010,2010,2010,2010,2010,2010,2010,2011,2011,...,2021,2021 40monthlist 41>1,2,3,4,5,6,....,10,11,12 42length(datelist_s) 43>144 44length(datelist_s) 45>144 46length(yearlist) 47>144 48length(monthlist) 49>144 50 51#3 都道府県リスト作成 52 53pref_list <- c("北海道", "青森県","岩手県","宮城県","秋田県","山形県","福島県","茨城県","栃木県","群馬県","埼玉県","千葉県","東京都","神奈川県","新潟県","富山県","石川県","福井県","山梨県","長野県","岐阜県","静岡県","愛知県","三重県","滋賀県","京都府","大阪府","兵庫県","奈良県","和歌山県","鳥取県","島根県","岡山県","広島県","山口県","徳島県","香川県","愛媛県","高知県","福岡県","佐賀県","長崎県","熊本県","大分県","宮崎県","鹿児島県","沖縄県") 54 55pref_list2 <- paste0("^",pref_list) #都道府県名リスト、演算子付きリストを作成。 56P <- length(pref_list) #都道府県数 57 58#4 表を作るための関数を制作。 59createEmptyDf = function( nrow, ncol, colnames = c() ){ 60 if( missing( ncol ) && length( colnames ) > 0 ){ 61 ncol = length( colnames ) 62 } 63 data.frame( matrix( vector(), nrow, ncol, dimnames = list( c(), colnames ) ) ) 64} 65 66#5 パネルデータ作成 67 68#パネルデータ用の元の表を作成 69paneldata = createEmptyDf(P*T ,colnames = c("pref_name", "year", "month","patent")) 70 71 72#パネルデータを作成。 73for (pref in 1:P) {#上から都道府県ごとにデータを抽出 74 for (time in 1:T) {#各都道府県における各年月のデータを抽出 75 paneldata[(pref-1)*T+time, 1] = pref_list[pref] #1列目:都道府県 76 paneldata[(pref-1)*T+time, 2] = yearlist[time]  #2列目:年 77 paneldata[(pref-1)*T+time, 3] = monthlist[time] #3列目:月 78 paneldata[(pref-1)*T+time, 4] =           #4列目:合計数 79 .data = hyozyun %>% #元データを選択 80 filter(acai_app_dt >= datelist_s[time],acai_app_dt <= datelist_e[time]) %>% #同行の年月範囲のデータを抽出 81 filter(str_detect(abii_addr, pref_list2[pref])) %>% #同行の県に住所を置くデータを抽出 82 count() #抽出したの行数を合計 83 84 } 85}

上記のコード(というより最後の2重for構文)で膨大な時間がかかっているため、なるべく迅速なコードに変更したいです。ご存じの方がもしいらっしゃいましたら教えていただければ幸いです。

試したこと

素人ながら調べたところ、Rとforの相性が悪い、何度もfor構文の中で同じ呼び出しをしているなどを行っていると遅くなりやすいとありましたが、こちらの上手い変更方法が思いつきません。
またhyozyunデータを数万行削減したりしましたが、あまり効果はありませんでしたので、この構文を迅速化しなければならないようです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こういうときはまず県・年・月の項目をさくっと追加してしまいます。
次に集計ですが、Rにおいてはforループはできるだけ避けるのがいいです。場合にもよりますが、関数で処理したほうが早くなることが多いとされています。
こう云う目的だとtidyverse(dplyr)というドンピシャリな機能を提供してくれるパッケージがあります。

library(tidyverse) df1 <- read.table(encoding = "utf-8", text=" app_num abii_name abii_addr acai_app_dt 2012000001 中山 明 埼玉県所沢市 20100101 2012000002 浦下 不比等 神奈川県横浜市 20100101 2012000003 高元 和人 東京都中野区 20100101 2012000004 岩澤 あや 高知県高知市 20100101 2012000009 手越 広一郎 東京都調布市 20100103 2012000009 手越 広明 東京都調布市 20100103 2012000010 市川 孝明 愛知県北名古屋市 20100104 2012000010 近藤 裕一 愛知県北名古屋市 20100104 2012000011 ウァング,ジョナサン エイ アメリカ合衆国 20100104 ", sep="\t", stringsAsFactors=F, header=T) df1 %>% mutate(pref = regmatches(abii_addr, regexpr("(.*県|北海道|東京都|大阪府|京都府|)", abii_addr))) %>% mutate(year = substr(acai_app_dt, 1,4)) %>% mutate(month = substr(acai_app_dt, 5,6)) -> df2 df2 %>% group_by(pref,year,month) %>% summarize(value = n()) -> df3 print(df3)

投稿2022/12/15 09:48

KojiDoi

総合スコア13671

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問