Rの実際の衚圢匏デヌタの分析ず芖芚化

この資料は、衚圢匏のデヌタを分析するためのツヌルずしおR蚀語を孊習し、䞻芁な凊理ステップの実装の暪断的な䟋を確認したい人に圹立ちたす。

以䞋は、csvファむルからのデヌタの読み蟌み、デヌタクレンゞング芁玠を䜿甚したテキスト文字列の解析、分析枬定からのデヌタの集蚈、およびチャヌトのプロットを瀺しおいたす。

この䟋では、data.table、reshape2、stringdist、ggplot2パッケヌゞの機胜を積極的に䜿甚しおいたす。



モスクワでのタクシヌによる乗客および手荷物の茞送に関する掻動を実斜するために発行された蚱可に関する情報は、「実際のデヌタ」ずみなされたした。 モスクワの運茞省および道路亀通むンフラの開発郚門が䞀般的に䜿甚するために提䟛されたデヌタ。 デヌタセットdata.mos.ru/datasets/655ペヌゞ

゜ヌスデヌタの圢匏は次のずおりです。

ROWNUM;VEHICLE_NUM;FULL_NAME;BLANK_NUM;VEHICLE_BRAND_MODEL;INN;OGRN 1;"248197";" «-»";"017263";"FORD FOCUS";"7734653292";"1117746207578" 2;"249197";" «-»";"017264";"FORD FOCUS";"7734653292";"1117746207578" 3;"245197";" «-»";"017265";"FORD FOCUS";"7734653292";"1117746207578" ```
      
      





1.䞀次デヌタをダりンロヌドする
デヌタはサむトから盎接ダりンロヌドできたす。 ロヌドの過皋で、すぐに䟿利な方法で列の名前を倉曎したす。

 url <- "http://data.mos.ru/datasets/download/655" colnames = c("RowNumber", "RegPlate", "LegalName", "DocNum", "Car", "INN", "OGRN", "Void") rawdata <- read.table(url, header = TRUE, sep = ";", colClasses = c("numeric", rep("character",6), NA), col.names = colnames, strip.white = TRUE, blank.lines.skip = TRUE, stringsAsFactors = FALSE, encoding = "UTF-8")
      
      



これで、分析ず芖芚化を開始できたす...



2.デヌタ倉換
ラむセンシヌの組織圢態ず自動車のブランドに応じお、タクシヌずしお登録された自動車の台数の分垃を分析する必芁があるずしたす。 察応するデヌタは個別に匷調衚瀺されたせんが、すべおの必芁な情報はフィヌルドFULL_NAMELegalNameに名前が倉曎されたしたおよびVEHICLE_BRAND_MODEL車に含たれおいたす。

゜ヌスデヌタを倉換する過皋で、

簡単にするために、LegalNameフィヌルドずCarフィヌルドの最初の単語はそれぞれ、法的圢匏ずマシンのメヌカヌであるず考えおいたす䟋倖をどうするかは以䞋で明らかになりたす。 䞍芁なフィヌルドは、移怍可胜なフィヌルドの明瀺的なリストを䜿甚しお、data.frameからdata.tableぞの倉換䞭に自動的に砎棄されたす。

 ptn <- "^(.+?) (.+)$" # regexp pattern to match first word dt <- data.table(rawdata)[, list(RegPlate, LegalName, Car, OGRN, OrgType = gsub(ptn, "\\1" , toupper( LegalName )), CarBrand = gsub(ptn, "\\1", toupper( Car ))) ] rm(rawdata) # Clear some memory
      
      





3.最初の結果
デヌタから抜出された組織フォヌムを確認したす。

 sort( table(dt$OrgType) )
      
      



 ##      ## 1 392 649 17118 17680
      
      



デヌタは非垞に正確に生成されたす。個々の起業家が受け取ったラむセンスの数をリヌドしおいたす枛皎、有限責任䌚瀟、オヌプンずクロヌズの合資䌚瀟、さらには1぀の非営利パヌトナヌシップがありたす。

法的圢匏に応じお、ラむセンスを受け取った独立したラむセンシヌ 車ではないの数を刀断するには、法人PSRNを䞀意に特城付けるフィヌルドを芁玄する必芁がありたす。

 dt[, list( N = length( unique(OGRN) ) ), by = OrgType][order(N, decreasing = TRUE)]
      
      



 ## OrgType N ## 1:  12352 ## 2:  563 ## 3:  14 ## 4:  6 ## 5:  1
      
      





デヌタクレンゞング

モスクワではどのブランドの車がタクシヌずしお䜿甚されおいたすか

デヌタセットには倚くの自動車ブランド115が含たれおいたすが、それらはすべお本圓にナニヌクですか 䟋ずしお、文字「M」で始たるすべおのマヌクを衚瀺したす。

 sort( unique( dt[grep("^M.*", CarBrand), CarBrand]))
      
      



 ## [1] "M214" "MASERATI" "MAZDA" ## [4] "MAZDA-" "MERCEDES" "MERCEDES-BENZ" ## [7] "MERCEDES-BENZ-" "MERCEDES-BENZ-S500" "MERCEDES-BENZC" ## [10] "MERCEDES-BENZE200K" "MERCEDES-BENZE220CDI" "MERCEDES-BNZ" ## [13] "MERCERDES-BENZ" "MERCRDES" "MERCRDES-BENZ" ## [16] "MERSEDES-" "MERSEDES-BENZ" "METROCAB" ## [19] "MG" "MINI" "MITSUBISHI"
      
      



残念ながら、倚くの自動車ブランドは䞻にデヌタ゚ラヌによるものです。 たずえば、同じブランド-MERCEDES-BENZ-はさたざたな名前で芋぀かりたす。 分析の前に、デヌタをクリアする必芁がありたす。

テキスト情報をクリアするためのプログラムの基瀎は、怜玢機胜「行間隔」です。 行のペアごずに、文字の操䜜を䜿甚しお1぀の行を別の行に倉換する耇雑さを特城付けるメトリックを蚈算したす。 行が類䌌しおいるほど、必芁な操䜜は少なくなりたす。 理想的には、同じラむンの距離はれロで、最も類䌌しおいないラむンの距離は1にする必芁がありたす。 これは、同じ名前のパッケヌゞのstringdist関数のJaro-Winklerアルゎリズムが正確に機胜する方法です。

数行を比范したすが、距離ではなく、類䌌床である1-stringdistをカりントしたしょう。

 1 - stringdist( c("MERCEDES","MERSEDES","MAZDA","RENAULT","SAAB"), "MERCEDES", method = "jw", p = 0.1)
      
      



 ## [1] 1.0000 0.9417 0.5950 0.3452 0.0000
      
      



䞀芋、デヌタクリヌニングタスクは単玔に解決されたす。各レコヌドに぀いお、ディレクトリから最も類䌌した倀を遞択するだけで十分です。 残念ながら、このアプロヌチは垞に機胜するずは限りたせん。 たず、ディレクトリが珟圚の堎合のようにそうでない堎合がありたす。 第二に、正確な参照であっおも、状況によっおは手動でデヌタを修正する必芁がありたす。 たずえば、メ゜ッドの芳点からは、3぀のブランドが誀った倀「BAZ」の代替ずしお同等に適しおいたす。

 1 - stringdist("BAZ", c("VAZ", "UAZ", "ZAZ"), method = "jw", p = 0.1)
      
      



 ## [1] 0.7778 0.7778 0.7778
      
      



以䞋では半自動修正方法を䜿甚したす。これにより、アナリストが同意たたは手動で修正できる修正オプションをプログラムで生成するこずにより、デヌタクレンゞングの専門家の䜜業が倧幅に促進されたす。

゚ラヌの数が少ない倧量のデヌタでは、頻繁に発生する倀が正しいず芋なされ、゚ラヌが発生するこずはほずんどありたせん。 頻床倀は重み係数ずしお䜿甚され、行の近接メトリックが比䟋しお増加したす。 頻繁に出䌚う自動車ブランドが類䌌性ではなく量のために前進しないようにするために、しきい倀t



を超える類䌌床の倀のメトリックのみが考慮されたす t



遞択に぀いお。 したがっお、マシンのブランドの可胜な倀ごずに、掚奚される「参照」倀が同じデヌタセットから決定されたす。 「ブランド-修正案」のペアがcsvファむルに出力されたす。 分析ず修正の埌、修正されたcsvファむルがダりンロヌドされ、蟞曞ずしお機胜したす。

たず、既存のデヌタセットに最適な関数を返す関数を䜜成したす。

 bestmatch.gen <- function(wc, t = 0){ # wc = counts of all base text words # t = threshold: only the words with similarity above threshold count bestmatch <- function(a){ sim <- 1 - stringdist( toupper(a), toupper( names(wc) ) , method = "jw", p = 0.1 ) # Compute weights and implicitly cut off everything below threshold weights <- sim * wc * (sim > t) # Return the one with maximum combined weight names( sort(weights, decr = TRUE)[1] ) } bestmatch }
      
      



t



のしきい倀t



経隓的に遞択されたす。 しきい倀パラメヌタヌt = 0.7に察する関数の動䜜䟋を次に瀺したす。

  bm07 <- bestmatch.gen( table( dt$CarBrand), t = 0.7 ) s <- c("FORD","RENO","MERS","PEGO") sapply(s, bm07)
      
      



 ## FORD RENO MERS PEGO ## "FORD" "RENAULT" "MERCEDES-BENZ" "PEUGEOT"
      
      



䞀芋、すべおが玠晎らしく機胜したした。 しかし、喜ぶには早すぎたす。 デヌタセットでよく衚されおいる類䌌した名前のよく衚されおいる自動車ブランドは、他の正しい名前を「プルオヌバヌ」できたす。

 s <- c("HONDA", "CHRYSLER", "VOLVO") sapply(s, bm07)
      
      



 ## HONDA CHRYSLER VOLVO ## "HYUNDAI" "CHEVROLET" "VOLKSWAGEN"
      
      



しきい倀tを増やしおみたしょう。

 bm09 <- bestmatch.gen( table( dt$CarBrand), t = 0.9 ) s <- c("HONDA","CHRYSLER","VOLVO") sapply(s, bm09)
      
      



 ## HONDA CHRYSLER VOLVO ## "HONDA" "CHRYSLER" "VOLVO"
      
      



倧䞈倫ですか ほが。 異なる線のクリッピングが硬すぎるず、アルゎリズムがいく぀かの誀った倀を正しいずみなすずいう事実に぀ながりたす。 このような゚ラヌは手動で修正する必芁がありたす。

 s <- c("CEAT", "CVEVROLET") sapply(s, bm09)
      
      



 ## CEAT CVEVROLET ## "CEAT" "CVEVROLET"
      
      



これで、すべおのブランドのマシンに固有の倀の蟞曞ファむルを䜜成する準備が敎いたした。 ファむルは手動で線集する必芁があるため、提案された眮換が元の倀ず異なるかどうかを瀺す远加フィヌルドこれは垞に明らかではない、ブランド名が衚瀺される頻床、およびレコヌドに泚意を匕くラベルがあれば䟿利ですセットのいく぀かの統蚈的特性。 この堎合、アルゎリズムがたれなおそらく誀った倀を正しい倀ずしお提䟛する状況をキャッチしたいず思いたす。

 ncb <- table(dt$CarBrand) scb <- names(ncb) # Source Car Brands acb <- sapply(scb, bm09) # Auto-generated replacement cbdict_out <- data.table(ncb)[,list( SourceName = scb, AutoName = acb, SourceFreq = as.numeric(ncb), AutoFreq = as.numeric( ncb[acb] ), Action = ordered( scb == acb, labels = c("CHANGE","KEEP")), DictName = acb )] # Add alert flag # Alert when suggested is a low-frequency dictionary word cbdict_out <- cbdict_out[, Alert := ordered( AutoFreq <= quantile(AutoFreq, probs = 0.05, na.rm = TRUE), labels = c("GOOD","ALERT")) ] write.table( cbdict_out[ order(SourceName), list( Alert, Action, SourceName, AutoName, SourceFreq, AutoFreq, DictName) ], "cbdict_out.txt", sep = ";", quote = TRUE, col.names = TRUE, row.name = FALSE, fileEncoding = "UTF-8")
      
      



DictNameフィヌルドの倀を確認および線集し、その埌のダりンロヌドのために「cbdict_in.txt」ずいう名前でファむルを保存する必芁がありたす。

分析されたデヌタセットには、次の点に泚意する䟡倀のある機胜がありたす。

デヌタの機胜に加えお、手動で調敎する必芁があるアルゎリズムの制限がありたす。 線集したデヌタをcbdict_in.txtファむルからロヌドしたす。

 if ( file.exists("cbdict_in.txt")) url <- "cbdict_in.txt" else url <- "cbdict_out.txt" cbdict_in <- read.table( url, header = TRUE, sep = ";", colClasses = c( rep("character",4), "numeric", "numeric", "character"), encoding = "UTF-8") cbdict <- cbdict_in$DictName names(cbdict) <- cbdict_in$SourceName
      
      



そしお、デヌタ衚の自動車のブランドの倀を修正したす。

 dt[, CarBrand := cbdict[CarBrand]] dt[is.na(CarBrand), CarBrand := "UNKNOWN"]
      
      



車のブランドのナニヌクな䟡倀をきれいにした埌、それはほが半分になりたした

 length( unique(dt$CarBrand) )
      
      



 ## [1] 72
      
      





分析的な質問ぞの回答

1.トップ10組織
10の最倧のタクシヌ公園を定矩したす。 この堎合、PSRNずいう1぀のディメンションの評䟡を䜜成する必芁がありたす。

 st <- dt[, list( NumCars = length(RegPlate)), by = list(OGRN, LegalName) ] head( st[order( NumCars, decreasing = TRUE)], 10)
      
      



 ## OGRN LegalName NumCars ## 1: 1137746197104  «» 866 ## 2: 1037727000893  «-» 751 ## 3: 1067746273198  « » 547 ## 4: 1037789018849  «» 541 ## 5: 1127746010700  «-24 » 406 ## 6: 1057748223653  «» 349 ## 7: 5067746596297  «» 288 ## 8: 1027739272175  «14 » 267 ## 9: 1137746133250  « » 255 ## 10: 5077746757688  «» 238
      
      



残念ながら、このデヌタセットには、ラむセンシヌに関する法的情報のみが保存され、商暙ではありたせん。 むンタヌネット䞊では、組織の名前ずOGRNによっお、タクシヌ䌚瀟がどのブランドで運営されおいるかを芋぀けるこずができたすが、このプロセスは自動ではなく、時間がかかりたす。 最倧のタクシヌ車䞡の怜玢結果は、ファむル「 top10orgs.csv 」に収集されたす。

 top10orgs <- data.table( read.table( "top10orgs.csv", header = TRUE, sep = ";", colClasses = "character", encoding = "UTF-8"))
      
      



data.tableの組み蟌み機胜を䜿甚しお、2぀のテヌブルのJOIN操䜜を実行したす。

 setkey(top10orgs,OGRN) setkey(st,OGRN) st[top10orgs][order(NumCars, decreasing = TRUE), list(OrgBrand, EasyPhone, NumCars)]
      
      



 ## OrgBrand EasyPhone NumCars ## 1:  781 81 82 866 ## 2: 956 956 8 956 751 ## 3: - 641 11 11 547 ## 4:   500 0 500 541 ## 5: 24 777 66 24 406 ## 6:   777 5 777 349 ## 7:    940 88 88 288 ## 8: 14  707 2 707 267 ## 9: Cabby 21 21 989 255 ## 10:  927 11 11 238
      
      





2.法人の圢態に応じお、最も人気のある3぀の自動車ブランド
ラむセンシヌの法的圢態に応じお、どのブランドの車が最も人気がありたすか この質問に答えるには、マシンの構成ず組織圢態ずいう2぀の次元でデヌタを集玄する必芁がありたす。

プロセスは3段階に分けられたす。

  1. 集蚈されたむンゞケヌタヌの蚈算この堎合、PSRNに基づく車の数。
  2. ランク蚈算。
  3. ランク制限䞊䜍3、䞊べ替え、列の再配垃、およびデヌタ出力。


 st <- dt[, list(AGGR = length(RegPlate)), by = list(OrgType, CarBrand) ] st.r <- st[, list(CarBrand, AGGR, r = ( 1 + length(AGGR) - rank(AGGR, ties.method="first"))), by = list(OrgType)] # ranking by one dimension st.out <- st.r[ r <= 3 ][, list(r, OrgType, cval = paste0(CarBrand," (",AGGR,")"))] dcast(st.out, r ~ OrgType, value.var = "cval")[-1] # reshape data and hide r
      
      



 ##      ## 1 FORD (212) CHEVROLET (2465) VOLVO (1) KIA (192) FORD (3297) ## 2 RENAULT (175) FORD (2238) <NA> CHEVROLET (115) RENAULT (2922) ## 3 HYUNDAI (122) RENAULT (1996) <NA> FORD (53) HYUNDAI (2812)
      
      





可芖化

1.円グラフデヌタの衚瀺
円グラフ、円グラフは、ビゞネス環境で非垞に人気がありたすが、デヌタ分析の専門家によっお批刀されおいたす。 それにもかかわらず、それは「調理する」こずができなければなりたせん。

車でのタクシヌ免蚱蚌の数の分垃を衚瀺するずしたす。 図をオヌバヌロヌドしないために、少なくずも1000ラむセンスのブランドのみを衚瀺したす。

 st <- dt[, list(N = length(RegPlate)), by = CarBrand ] # Summary table st <- st[, CarBrand := reorder(CarBrand, N) ] piedata <- rbind( st[ N >= 1000 ][ order(N, decreasing=T) ], data.table( CarBrand = " ", N = sum( st[N < 1000]$N) ) ) piedata
      
      



 ## CarBrand N ## 1: FORD 5800 ## 2: RENAULT 5093 ## 3: HYUNDAI 4727 ## 4: CHEVROLET 4660 ## 5: KIA 2220 ## 6: SKODA 2073 ## 7: NISSAN 1321 ## 8: VOLKSWAGEN 1298 ## 9: TOYOTA 1075 ## 10: MERCEDES-BENZ 1039 ## 11:   6534
      
      



スケゞュヌルを䜜成するには、このような䞀連のスタンプを修正したいず思いたす。 これを行わないず、自動゜ヌトにより「その他のブランド」が最埌から最初に衚瀺されたす。

 piedata <- piedata[, CarBrand := factor(CarBrand, levels = CarBrand, ordered = TRUE)]
      
      



チャヌトを䜜成するには、ggplot2を䜿甚したす。

 pie <- ggplot(piedata, aes( x = "", y = N, fill = CarBrand)) + geom_bar(stat = "identity") + coord_polar(theta = "y") pie
      
      



plot of chunk pie_1

結論はすでに非垞に有益です。 しかし、私はいく぀かの芖芚的な改善をしたいず思いたす

以䞋のコヌドを䜿甚するず、䞊蚘のすべおを実行できたす。 セクタヌの暪にラベルを衚瀺するには、セクタヌの䞭心点の蚈算を含むフィヌルドを远加する必芁がありたした artelstatistikov.ruを参照 。

 piedata <- piedata[, pos := cumsum(N) - 0.5*N ] pie <- ggplot(piedata, aes( x = "", y = N, fill = CarBrand)) + geom_bar( color = "black", stat = "identity", width = 0.5) + geom_text( aes(label = N, y = pos), x = 1.4, color = "black", size = 5) + scale_fill_brewer(palette = "Paired", name = " ") + coord_polar(theta = "y") + theme_bw() + theme ( panel.border = element_blank() , panel.grid.major = element_blank() , axis.ticks = element_blank() , axis.title.x = element_blank() , axis.title.y = element_blank() , axis.text.x = element_blank() , legend.title = element_text(face="plain", size=16) ) pie
      
      



plot of chunk pie_2
2.棒グラフ
円のより有益な代替手段は、棒グラフ、棒グラフです。 列の長さを円匧の長さたたは円セクタヌの面積よりも比范する方が䟿利であるずいう事実に加えお、棒グラフは、たずえば、組織圢態ごずのラむセンス数の分垃を衚瀺できたす。

 st <- dt[, list(N = length(RegPlate)), by = list(OrgType, CarBrand) ] # Summary table cbsort <- st[, list( S = sum(N) ), keyby = CarBrand ] # Order by total number setkey(st, CarBrand) st <- st[cbsort] # Join topcb <- st[ S >= 1000 ][ order(S) ] bottomcb <- st[S < 1000, list(CarBrand = " ", OrgType, N = sum(N)), by = OrgType] bottomcb <- bottomcb[, list(CarBrand, OrgType, N, S = sum(N))] bardata <- rbind( bottomcb, topcb) bardata <- bardata[, CarBrand := factor(CarBrand, levels = unique(CarBrand), ordered=T)] # bar <- ggplot(bardata, aes(x = CarBrand, weight = N, fill = OrgType)) + geom_bar() + coord_flip() + scale_fill_brewer(palette = "Spectral", name = "") + labs(list(y = " ", x = " ")) + theme_bw() bar
      
      



plot of chunk bar

3.ヒヌトマップ図
「タクシヌドラむバヌの䞭で、どの自動車ブランドの所有者が最も矎しい」「矎しい「数字」なのか」ずいう質問に察する答えを埗たいずしたす。 この堎合、トリプル、111、222などの同じ数字を持぀矎しい数字を怜蚎したす。

分析は、自動車のブランドず3぀の2぀の分析ディメンションで実行されたす。 指暙-ブランドずトリプルの特定の組み合わせを持぀車の数。 このようなデヌタセットを芖芚化するには、衚の芖芚的な類䌌物であるヒヌトマップ図が適しおいたす。 トリプルの人気が高いほど、色はセルの倀をより匷く゚ンコヌドしたす。

 ln <- dt[grep( "^[^0-9]([0-9])\\1{2}.+$" , RegPlate), list(CarBrand, LuckyNum = gsub("^[^0-9]([0-9]{3}).+$","\\1", RegPlate))] ln <- ln[, list( N = .N), by = list(CarBrand, LuckyNum) ] ln <- ln[, Luck := sum(N), by = list(CarBrand) ] # Total number of lucky regplates per car brand ln <- ln[, CarBrand := reorder(CarBrand, Luck) ] # heatmap <- ggplot(ln, aes(x = CarBrand, y = LuckyNum)) + geom_tile( aes(fill = as.character(N)), color = "black") + scale_fill_brewer(palette = "YlOrRd", name = " «» :") + labs(list(x = " ", y = " ")) + theme_bw() + theme ( panel.grid.major = element_blank() , axis.text.x = element_text(angle = 45, hjust = 1) , axis.title.y = element_text(vjust = 0.3) , legend.position = "top" , legend.title.align = 1 ) heatmap
      
      



plot of chunk lucky_numbers

すべおの図は、 Color Brewer 2.0プロゞェクトの科孊に基づいたカラヌパレットを䜿甚したす。



All Articles