-3

2 つの非常に大きなデータ (nsar & crsp) セットを照合しようとしています。私のコードは非常にうまく機能しますが、多くの時間が必要です。私の手順は次のように機能します。

  1. ティッカーを介して一致を試みます (それにより、その NAV (数値のみ) と日付を制御します)
  2. 正確なファンド名で一致を試す (NAV と日付を制御)
  3. 最も近い一致で一致を試行: 最初に同じ NAV と日付を検索します --> リストを取得し、両方の一致測定値で最も一致する企業のみを検討します --> 残りのエントリを取得して、最も近い一致を見つけます (ただし、一致距離は制限されています)。

コードの効率を改善する方法についての提案:

#Go through each nsar entry and try to match with crsp
trackchanges = sapply(seq_along(nsar$fund),function(x){

    #Define vars
    ticker = nsar$ticker[x]
    r_date = format(nsar$r_date[x], "%m%Y")
    nav1 = nsar$NAV_share[x]
    nav2 = nsar$NAV_sshare[x]
    searchbyname = 0

    if(nav1 == 0) nav1 = -99
    if(nav2 == 0) nav2 = -99

    ########## If ticker is available --> Merge via ticker and NAV
    if(is.na(ticker) == F)
    {

        #Look for same NAV, date and ticker
        found = which(crsp$nasdaq == ticker & crsp$caldt2 == r_date & (round(crsp$mnav,1) == round(nav1,1) | round(crsp$mnav,1) == round(nav2,1)))


        #If nothing found
        if(length(found) == 0)
        {

            #Mark that you should search by names
            searchbyname = 1

        } else { #ticker found 

                    #Record crsp_fundno and that match is found
            nsar$match[x] = 1 
            nsar$crsp_fundno[x] = crsp$crsp_fundno[found[1]] 
            assign("nsar",nsar,envir=.GlobalEnv)

            #Return: 1 --> Merged by ticker
            return(1)
        }

    } 

    ###########

    ########### No Ticker available or found --> Exact name matching
    if(is.na(ticker) == T | searchbyname == 1)
    {

        #Define vars
        name = tolower(nsar$fund[x])
        company = tolower(nsar$company[x])

        #Exact name, date and same NAV
        found = which(crsp$fund_name2 == name & crsp$caldt2 == r_date & (round(crsp$mnav,1) == round(nav1,1) | round(crsp$mnav,1) == round(nav2,1)))



        #If nothing found
        if(length(found) == 0)
        {

            #####Continue searching by closest match

                #First search for nav and date to get list of funds
                allfunds = which(crsp$caldt2 == r_date & (round(crsp$mnav,1) == round(nav1,1) | round(crsp$mnav,1) == round(nav2,1)))
                allfunds_companies = crsp$company[allfunds]

                #Check if anything found
                if(length(allfunds) == 0)
                {
                    #Return: 0 --> nothing found
                    return(0)
                }

                #Get best match by lev and substring measure for company
                levmatch = levenstheinMatch(company, allfunds_companies)
                submatch = substringMatch(company, allfunds_companies)

                allfunds = levmatch[levmatch %in% submatch]
                allfunds_names = crsp$fund_name2[allfunds]

                #Check if now anything found
                if(length(allfunds) == 0)
                {
                    #Mark match (5=Company not found)
                    nsar$match[x] = 5 

                    #Save globally
                    assign("nsar",nsar,envir=.GlobalEnv)

                    #Return: 5 --> Company not found
                    return(5)
                }


                #Get best match by all measures
                levmatch = levenstheinMatch(name, allfunds_names)
                submatch = substringMatch(name, allfunds_names)


                #Only accept if identical
                allfunds = levmatch[levmatch %in% submatch]
                allfunds_names = crsp$fund_name2[allfunds]


                if(length(allfunds) > 0)
                {
                    #Mark match (3=closest name matching)
                    nsar$match[x] = 3 

                    #Add crsp_fundno to nsar data
                    nsar$crsp_fundno[x] = crsp$crsp_fundno[allfunds[1]] 

                    #Save globally
                    assign("nsar",nsar,envir=.GlobalEnv)

                    #Return 3=closest name matching
                    return(3)

                } else {
                    #return 0 -> no match
                    return(0)
                }

            #####

        } else { #If exact name,date,nav found

            #Mark match (2=exact name matching)
            nsar$match[x] = 2 

            #Add crsp_fundno to nsar data
            nsar$crsp_fundno[x] = crsp$crsp_fundno[found[1]] 

            #Return 2=exact name matching
            return(2)
        }
    }   





})#End sapply

助けてくれてありがとう!ローレンツ

4

1 に答える 1

2

スクリプトは複雑すぎて完全な回答を提供できませんが、基本的な問題は最初の行にあります

#Go through each nsar entry...

反復的な方法で問題を設定する場所。R はベクトルで最適に機能します。

計算sapplyを開始するからベクトル化可能なコンポーネントを持ち上げます。たとえば、r_date をフォーマットします。

nsar$r_date_f <- format(nsar$r_date, "%m%Y")

このアドバイスは、コードの奥深くに埋め込まれた行にも適用されます。たとえば、丸められた crsp$mnav の計算は、列全体で 1 回だけ実行する必要があります。

crsp$mnav_r <- round(crsp$mnav, 1)

必要に応じてR イディオムを使用します。「-99」が欠損値を表す場合は、NA を使用します

nav1 <- nsar$NAV_share
nav1[nav1 == -99] <- NA
nasr$nav1 <- nav1

使用する可能性のある他のパッケージのコードは、NA を正しく処理する可能性が高くなります。

より複雑なクエリには、確立された R 関数を使用します。これは注意が必要ですが、コードを正しく読んでいれば、「同じ NAV、日付、ティッカー」に関するクエリを使用mergeして結合を行うことができます。

nasr1 <- nasr[!is.na(nasr$ticker), , drop=FALSE]
df0 <- merge(nasr1, crsp, 
             by.x = c("ticker", rdate_r", "nav1_r"),
             by.y = c("nasdaq", "caldt2", "mnav_r"))

これは「|」をカバーしません。状態ですので追加工が必要となります。plyr、data.table、および sqldf パッケージ (特に) は、これらのタイプの操作を簡素化するために開発されたものであるため、ベクトル化された計算に慣れてきたら調査する価値があるかもしれません。

見分けるのは難しいですが、これらの 3 つのステップでコードの主要な課題に対処できると思います。

于 2013-04-26T13:36:30.390 に答える