每當我看到一個說「1或更多」的問題時,我傾向於考慮一次做某件事,然後迭代向量或列表中的所有項目。你開始以這種方式思考,但在你的循環中,你每次分配而不是URL
,只保存最後一個。即使你保存了所有的URL,但是,GET
一次只能檢索一個,所以你也需要重複這個函數。
這個演示大多是概念,沒有真正的證明它的工作原理。由於您在問題中包含了實際的API密鑰,因此它已經用盡。 (你可能想從問題中刪除它)。無論如何,我對將這些函數應用於一系列事物的概念有點自信,所以儘管我沒有證實你得到了一個巨大的data.frame,也許我會幸運的。
z <- expand.grid(lon = seq(-124.4531, -68.02734, by=5.9180),
lat = seq(25.7998, 49.0090, by=5.6667))
head(z)
# lon lat
# 1 -124.4531 25.7998
# 2 -118.5351 25.7998
# 3 -112.6171 25.7998
# 4 -106.6991 25.7998
# 5 -100.7811 25.7998
# 6 -94.8631 25.7998
mapply
(和Map
)通過施加從載體/列表1以上參數的單一功能的工作(第一個參數)。在某些語言中,它被認爲是「拉大論點」。試想一下:
mapply(function(x,y,z) x+y-z,
c(1,2,3,4), c(5,6,7,8), c(9,10,11,12))
第一次調用匿名函數將執行1+5-9
;第二,2+6-10
;等有進一步的技巧,利用這一點,但回頭看你的問題:
URLs <- mapply(sprintf,
list("https://maps.googleapis.com/maps/api/place/radarsearch/json?location=%s,%s&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"),
z$lat, z$lon)
(編輯:我以前有z$lat
和z$lon
逆轉mapply
內,固定)
功能sprintf
接受任意數量的參數:第一個始終是格式化字符串,第二個和以後(如果有的話)始終是填充格式化字符串的參數/對象。所述list("htt...")
參數只是提供了參數的sprintf
每個呼叫,所以函數調用細分爲:
sprintf("https...", z$lon[1], z$lon[2])
sprintf("https...", z$lon[2], z$lon[2])
# ...
sprintf("https...", z$lon[50], z$lon[50])
這些呼叫被包裹回一個character
矢量,長度爲50。
(URLs <- head(URLs)) # doing this for a simpler demo, since I don't need all 50
# [1] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-124.4531,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"
# [2] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-118.5351,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"
# [3] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-112.6171,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"
# [4] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-106.6991,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"
# [5] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-100.7811,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"
# [6] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-94.8631,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"
我們仍然有「1個或多個」列表中,這樣我們就可以繼續使用lapply
邏輯:
HTMLs <- lapply(URLs, GET)
HTMLs[1]
# [[1]]
# Response [https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-124.4531,25.7998&radius=50000&name=MetroPCS]
# Date: 2017-10-18 03:23
# Status: 200
# Content-Type: application/json; charset=UTF-8
# Size: 141 B
# {
# "error_message" : "This service requires an API key.",
# "html_attributions" : [],
# "results" : [],
# "status" : "REQUEST_DENIED"
# }
在這種情況下,我得到一個失敗(這將削弱我能做什麼以後),但是這個輸出告訴你,你的HTMLs
變量應該是50的長度,每個都是這樣的。
繼續,雖然從這裏開始它沒有經過測試。我相信你已經測試過這個功能,一次只能使用一個URL。
contents <- lapply(HTMLs, content, "text")
myDataFrames <- lapply(contents, jsonlite::fromJSON)
這最後一個應該是data.frame
秒的名單,這是偉大的!我通常做的與此兩種情況之一:如果我可以輕鬆地將它們合併成一個單一的data.frame
,那麼怎麼辦?(rbind
?):
myDataFrame <- do.call(rbind.data.frame, c(myDataFrames, list(stringsAsFactors = FALSE)))
(採用stringsAsFactors
大多是風格,但顯示如何添加(如果你需要它們)。
但是,如果保持它們分開是有益的(也許它們不是同構的結構),那麼在列表上操作(重複使用lapply
或相關)仍然是非常容易的。
一個可以證明通過單個調用這個簡化了一下:
myDataFrames <- lapply(URLs, function(u) {
html <- GET(u)
cont <- cont(html, "text")
jsonlite::fromJSON(cont)
})
,這是沒有錯的。但是,特別是在開發過程中,保留不同對象的中間列表可能是有益的。
您是否在雙''''循環之間和之後查看了'URL'的值? 'print'-ing給控制檯帶來了一些東西,這對於一個「感覺良好」的時刻來說真的只是一件好事,但對後續代碼卻沒有任何作用。你需要捕獲它,也許通過預先分配一個大的矢量(不推薦)或者使用像'mapply'這樣的東西。 – r2evans
也許'URL < - mapply(sprintf,list(「https://maps.googleapis.com/maps/api/place/radarsearch/json?location=%s,%s」),z [,1],z [,2])'是一個開始? (我意識到在位置之後還有更多的字符串,我只是在這裏開始......如果您不熟悉,請查看['?sprintf'](https://stat.ethz.ch/ R-manual/R-devel/library/base/html/sprintf.html)。) – r2evans
@ r2evans,謝謝。 -mapply-在生成URL列表方面效果很好,但GET()循環似乎仍然只能運行最後的結果。不確定是否要執行GET()函數? – jessiez