Как перебрать в R функцию синтаксического анализа вызова / вывода API Zillow по списку адресов и почтовых индексов?

Я работал над проектом, цель которого - взять CSV из двух столбцов уличных адресов и почтовых индексов, прочитать его в R, а затем выполнить запрос Zillow для каждого (в частности, GetSearchResults), проанализировать вывод и сохраните проанализированный вывод в кадре данных, который будет записан в CSV (и помещен прямо рядом с существующими данными).

предостережение: я могу вызывать только один адрес / почтовый комбо за один раз через zillow API, так что все, что нарушает, немедленно исчезнет.

На данный момент, у меня есть около 85% выполненной работы. У меня есть i) немного кода, который может, один за другим, запрашивать эти комбинации адреса / почтового индекса из фрейма данных, а также ii) предварительный способ вернуть этот ввод обратно в фрейм данных,

library(ZillowR)
library(rvest)
library(dplyr)
library(DT)

# this commented section is what I would use instead of creating the dataframe manually below, just for clarity
# data1 = read.csv('Addresses.csv', header = F, colClasses = 'character')$V1
# data2 = read.csv('Addresses.csv', header = F, colClasses = 'character')$V2
# data = data.frame(street = data1, city.state = as.character(data2))
# per comments, should add a "stringsAsFactors = FALSE" in the dataframe part

data = data.frame(
    street = c('77 Huntington Ave',
             '85 Prospect St',
             '219 Lincoln St'),
    city.state = c(rep('01752', 3)))

get.zillowdata = function(df, address, city.state){
    require(ZillowR)
    set_zillow_web_service_id('API KEY')
    results = do.call(rbind, lapply(1:nrow(df), function(i){
        z = tryCatch({
        zdata = GetDeepSearchResults(address = df$street[i],
                  citystatezip = df$city.state[i],
                  zws_id = getOption("ZillowR-zws_id"),
                  url = "http://www.zillow.com/webservice/GetDeepSearchResults.htm")
        return(zdata)
    },

    error = function(cond) {
      message(paste("No Data Available:", df$street[i], df$city.state[i]))
      return(NA) # Choose a return value in case of error
    },

    warning = function(cond) {
      message(paste("Zdata caused a warning:", df$street[i], df$city.state[i]))
      return(NA) # Choose a return value in case of warning
    },
    # print processing message to screen
    finally = {
      message(paste("Processed Address:", df$street[i], df$city.state[i]))
      message(paste(i, "of", nrow(df), 'processed'))
      }
    )
    }))

if(nrow(results)==nrow(df)){
    results = cbind(df, results)

    print(paste('Original data had', nrow(df), 'rows. Returning a dataframe with', nrow(results),
    'rows. Returned dataframe has', sum(is.na(results$amount)), 'missing zdata values.'))

  return(results)
}
    else(print("Error: nrows(df) do not match nrows(zdata)"))
}

get.zillowdata(data)
` 

а также iii) синтаксический анализатор ответа XMLnode, который вы получаете, когда выполняете запрос через API Zillow, который выбирает конкретные дочерние значения (оценка, квадратный метраж, размер партии и т. д.; все, что вы укажете)

library(ZillowR)
library(XML)
library(RCurl)

set_zillow_web_service_id('API KEY')
output123 = GetDeepSearchResults(address = 'STREET ADDRESS', citystatezip = '0ZIP CODE', zws_id = getOption("ZillowR-zws_id"), url = "http://www.zillow.com/webservice/GetSearchResults.htm")

results <- xmlToList(output123$response[["results"]])

getValRange <- function(x, hilo) {
  ifelse(hilo %in% unlist(dimnames(x)), x["text",hilo][[1]], NA)
}

out <- apply(results, MAR=2, function(property) {
  zpid <- property$zpid
  links <- unlist(property$links)
  address <- unlist(property$address)
  z <- property$zestimate
  zestdf <- list(
    amount=ifelse("text" %in% names(z$amount), z$amount$text, NA),
    lastupdated=z$"last-updated",
    valueChange=ifelse(length(z$valueChange)==0, NA, z$valueChange),
    valueLow=getValRange(z$valuationRange, "low"),
    valueHigh=getValRange(z$valuationRange, "high"),
    percentile=z$percentile)
  list(id=zpid, links, address, zestdf)
})

data <- as.data.frame(do.call(rbind, lapply(out, unlist)),
                      row.names=seq_len(length(out)))

Но я немного застрял на этом этапе. Как я должен собрать их вместе, чтобы я мог включить разбор в конце части вызова API и убедиться, что они оба повторяются по всему списку адресов / почтовых индексов? Мой код сейчас не в каком-то конкретном порядке, поэтому не стесняйтесь перемещать вещи, если вы решите заняться этим, и если кому-то понадобится дополнительная информация, я с удовольствием уточню!

Большое спасибо заранее.

0 ответов

Это полуупрощенный ответ на ваш вопрос (я имею в виду, что я удалил часть информации, которую предоставляет api, например высокие и низкие оценки, но вы можете добавить их обратно, следуя логике для другой предоставленной информации в приведенном ниже коде). Первая загрузка необходимых пакетов:

ipak <- function(pkg){
new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
if (length(new.pkg)) 
install.packages(new.pkg, dependencies = TRUE)
sapply(pkg, require, character.only = TRUE)
}
#install and load the following packages 
packages <- c("ZillowR", "rjson", "httr", "XML")
ipak(packages)

Затем установите свой ключ API Zillow:

set_zillow_web_service_id('API KEY')

Затем определяем набор данных только с адресами, а затем определяем и добавляем в него столбцы с адресом улицы и почтовый индекс, чтобы мы могли использовать их позже с Zillow api:

df <-data.frame("Address" = c("5435 Andrea Boulevard, Sacramento, CA 95842","8434 Walerga Road Apt 421, Antelope, CA 95843"
       ,"7152 Flanders Way, Sacramento, CA 95842","1076 Edmonton Drive, Sacramento, CA 95833"    
       ,"9906 Burline Street, Sacramento, CA 95827","3634 Sapphire Drive Apt 1, Auburn, CA 95602"),stringsAsFactors = FALSE)
df$StreetCity<-gsub("(.*),.*", "\\1", df$Address)
df$Street<-gsub("(.*),.*", "\\1", df$StreetCity)
df$zip<-substr(df$Address,nchar(df$Address)-4,nchar(df$Address))
df
#                                         Address                          StreetCity                    Street   zip
# 1   5435 Andrea Boulevard, Sacramento, CA 95842   5435 Andrea Boulevard, Sacramento     5435 Andrea Boulevard 95842
# 2 8434 Walerga Road Apt 421, Antelope, CA 95843 8434 Walerga Road Apt 421, Antelope 8434 Walerga Road Apt 421 95843
# 3       7152 Flanders Way, Sacramento, CA 95842       7152 Flanders Way, Sacramento         7152 Flanders Way 95842
# 4     1076 Edmonton Drive, Sacramento, CA 95833     1076 Edmonton Drive, Sacramento       1076 Edmonton Drive 95833
# 5     9906 Burline Street, Sacramento, CA 95827     9906 Burline Street, Sacramento       9906 Burline Street 95827
# 6   3634 Sapphire Drive Apt 1, Auburn, CA 95602   3634 Sapphire Drive Apt 1, Auburn 3634 Sapphire Drive Apt 1 95602

Теперь перейдем к API:

getValRange <- function(x, hilo) {
  ifelse(hilo %in% unlist(dimnames(x)), x["text",hilo][[1]], NA)
}

Out_df_All <-NULL
Out_df <-NULL

for (i in 1:nrow(df)){
  print(i)
  xml =GetSearchResults(address = as.character(df[i,]$Street), citystatezip = as.character(df[i,]$zip),rentzestimate = TRUE)
  if (!is.null(xml$response[["results"]])){
    results <- xmlToList(xml$response[["results"]])
    if (is.matrix(results)){
      out <- apply(results, MAR=2, function(property) {
        zpid <- property$zpid
        links <- unlist(property$links)["mapthishome"]
        address <- unlist(property$address)
        z <-property$zestimate
        zestdf <- list(
          zestimate=ifelse("text" %in% names(z$amount), z$amount$text, NA)
        ) 

        rz <- property$rentzestimate
        rentalzestdf <- list(
          rentzestimate=ifelse("text" %in% names(rz$amount), rz$amount$text, NA)
        ) 
        list(zpid=zpid, links, address, zestdf, rentalzestdf)
      }


      )
      data <- as.data.frame(do.call(rbind, lapply(out, unlist)[1]),row.names=seq_len(length(out)))
      data[is.na(data)] <- 0
      Out_df<-data.frame("Address"=df[i,"Address"],data)
      Out_df_All<-rbind(Out_df,Out_df_All)
    }

    else {
      data<-as.data.frame(do.call(rbind, lapply(xml$response[["results"]][1], unlist)[1]),row.names=seq_len(length(xml$response[["results"]][1])))
      data<-data[which(grepl("text.value",colnames(data)))]
      colnames(data)<-gsub("children.","",colnames(data))
      colnames(data)<-gsub(".text.value","",colnames(data))
      colnames(data)<-gsub("address.","",colnames(data))
      colnames(data)<-gsub("links.","",colnames(data))
      colnames(data)<-gsub(".amount","",colnames(data))
      data <- data[,c("zpid","mapthishome","street","zipcode","city","state","latitude","longitude")]
      data$zestimate <- ifelse("zestimate" %in% colnames(data), data$zestimate, NA)
      data$rentzestimate <- ifelse("rentzestimate" %in% colnames(data), data$rentzestimate, NA)
      data[is.na(data)] <- 0
      Out_df<-data.frame("Address"=df[i,"Address"],data)
      Out_df_All<-rbind(Out_df,Out_df_All)

    }
  }
}
View(Out_df_All)

Другие вопросы по тегам