2016-11-03 7 views
3

データフレームの行を繰り返し処理し、各行の値を関数に渡して出力を印刷するには、いくつかの援助を探していますエクセルファイル、txtファイル、または単にコンソールにあります。Googleマップ用のデータフレーム行を繰り返すためのRコード

これの目的は、このウェブサイトに掲載されてい関数を使用して、マップをGoogleに(数百)距離/時間クエリの束を自動化することで次のように、そのウェブサイト上のhttp://www.nfactorialanalytics.com/r-vignette-for-the-week-finding-time-distance-between-two-places/

機能は次のとおりです。

library(XML) 
library(RCurl) 
distance2Points <- function(origin,destination){ 
results <- list(); 
xml.url <- paste0('http://maps.googleapis.com/maps/api/distancematrix/xml?origins=',origin,'&destinations=',destination,'&mode=driving&sensor=false') 
xmlfile <- xmlParse(getURL(xml.url)) 
dist <- xmlValue(xmlChildren(xpathApply(xmlfile,"//distance")[[1]])$value) 
time <- xmlValue(xmlChildren(xpathApply(xmlfile,"//duration")[[1]])$value) 
distance <- as.numeric(sub(" km","",dist)) 
time <- as.numeric(time)/60 
distance <- distance/1000 
results[['time']] <- time 
results[['dist']] <- distance 
return(results) 
} 

データフレームには、発信元郵便番号と宛先郵便番号(カナダ、ええ?)の2つの列が含まれます。私は初心者のRプログラマですので、read.tableを使ってtxtファイルをデータフレームにロードする方法を知っています。データフレームをどのくらい反復するか、distance2Points関数に値を渡して実行するたびにわかりません。これはforループかapply呼び出しのどちらかを使って行うことができると思いますか?

ありがとうございました!

編集:

それをシンプルに保つためには、どのように私から距離と時間の両方を返すために、これらの2行を反復処理に取り掛かる必要があります

> a <- c("L5B4P2","L5B4P2") 
> b <- c("M5E1E5", "A2N1T3") 
> postcodetest <- data.frame(a,b) 
> postcodetest 
     a  b 
1 L5B4P2 M5E1E5 
2 L5B4P2 A2N1T3 

データフレームの中に、私はこれら二つのベクトルを変換したいと仮定することができますdistance2Points関数?

+2

私は 'sapply'は機能あなたと、あなたがやりたいだろうと思います'sapply'の呼び出しで使用する関数としてここに示してあります。ただし、再現可能な例を提供していない場合は、より具体的にするのは難しいです。質問にデータのスニペットを含めるために 'dput'を使うことができれば、そうするでしょう。 – ulfelder

+0

@ulfelderこれは役立つかどうかはわかりませんが、私はサンプルデータフレームを作成して作業することにしました。自分の問題を解決するためにサップリーを使う方法がわからないので、それ以上のことはできません。お役に立てれば。 – macsmith

答えて

3

lapplyを使用してデータの各行の結果をリストにし、Reduce(rbind, [yourlist])を使用してそのリストを元のデータフレームに対応する行に連結する方法があります。これを行うには、元の関数のコードを1行のデータフレームを返すように微調整する必要があります。ここでこれを行っています。

distance2Points <- function(origin,destination){ 

    require(XML) 
    require(RCurl) 

    xml.url <- paste0('http://maps.googleapis.com/maps/api/distancematrix/xml?origins=',origin,'&destinations=',destination,'&mode=driving&sensor=false') 
    xmlfile <- xmlParse(getURL(xml.url)) 
    dist <- xmlValue(xmlChildren(xpathApply(xmlfile,"//distance")[[1]])$value) 
    time <- xmlValue(xmlChildren(xpathApply(xmlfile,"//duration")[[1]])$value) 
    distance <- as.numeric(sub(" km","",dist)) 
    time <- as.numeric(time)/60 
    distance <- distance/1000 
    # this gives you a one-row data frame instead of a list, b/c it's easy to rbind 
    results <- data.frame(time = time, distance = distance) 
    return(results) 
} 

# now apply that function rowwise to your data, using lapply, and roll the results 
# into a single data frame using Reduce(rbind) 
results <- Reduce(rbind, lapply(seq(nrow(postcodetest)), function(i) 
    distance2Points(postcodetest$a[i], postcodetest$b[i]))) 

の検索結果を自分のサンプルデータに適用される:あなたは、新しいオブジェクトを作成せずにこれを行うことを好むだろう場合

> results 
     time distance 
1 27.06667 27.062 
2 1797.80000 2369.311 

は、あなたも、時間と距離を計算するための別々の機能を書くことができ - またはそれらの出力をオプションとして持つ単一機能を使用して、sapplyまたはmutateを使用して元のデータフレームに新しい列を作成します。ここではそれがsapplyを使用して見えるかもしれません方法は次のとおりです。

distance2Points <- function(origin, destination, output){ 

    require(XML) 
    require(RCurl) 

    xml.url <- paste0('http://maps.googleapis.com/maps/api/distancematrix/xml?origins=', 
        origin, '&destinations=', destination, '&mode=driving&sensor=false') 

    xmlfile <- xmlParse(getURL(xml.url)) 

    if(output == "distance") { 

    y <- xmlValue(xmlChildren(xpathApply(xmlfile,"//distance")[[1]])$value) 
    y <- as.numeric(sub(" km", "", y))/1000 

    } else if(output == "time") { 

    y <- xmlValue(xmlChildren(xpathApply(xmlfile,"//duration")[[1]])$value) 
    y <- as.numeric(y)/60 

    } else { 

    y <- NA  

    } 

    return(y) 

} 

postcodetest$distance <- sapply(seq(nrow(postcodetest)), function(i) 
    distance2Points(postcodetest$a[i], postcodetest$b[i], "distance")) 

postcodetest$time <- sapply(seq(nrow(postcodetest)), function(i) 
    distance2Points(postcodetest$a[i], postcodetest$b[i], "time")) 

そして、ここでは、あなたがmutatedplyrパイプでそれを行うことができる方法です:

library(dplyr) 

postcodetest <- postcodetest %>% 
    mutate(distance = sapply(seq(nrow(postcodetest)), function(i) 
      distance2Points(a[i], b[i], "distance")), 
     time = sapply(seq(nrow(postcodetest)), function(i) 
      distance2Points(a[i], b[i], "time"))) 
+0

ありがとう@ulfelder!素晴らしい解決策!私はシンプルさが好きで、どのようにして結果をデータフレームに戻したのですか?私は今、どん​​な似たようなプロジェクトのためにも、将来再利用できるツールを持っているように感じます。 – macsmith

関連する問題