Рассчитать функцию восхода, которая работает с фреймом данных с помощью dplyr :: mutate? - PullRequest
0 голосов
/ 10 декабря 2018

У меня возникли проблемы с функцией, которую я написал при попытке применить ее к кадру данных для изменения в новом столбце

Я хочу добавить столбец к кадру данных, который рассчитывает время восхода / захода солнца для всехстроки на основе существующих столбцов для широты, долготы и даты.Расчет восхода / захода происходит из функции "sunriseset" из пакета maptools.

Ниже моя функция:

library(maptools)
library(tidyverse)

sunrise.set2 <- function (lat, long, date, timezone = "UTC", direction = c("sunrise", "sunset"), num.days = 1) 
{
        lat.long <- matrix(c(long, lat), nrow = 1)
        day <- as.POSIXct(date, tz = timezone)
        sequence <- seq(from = day, length.out = num.days, by = "days")
        sunrise <- sunriset(lat.long, sequence, direction = "sunrise", 
                            POSIXct = TRUE)
        sunset <- sunriset(lat.long, sequence, direction = "sunset", 
                           POSIXct = TRUE)
        ss <- data.frame(sunrise, sunset)
        ss <- ss[, -c(1, 3)]
        colnames(ss) <- c("sunrise", "sunset")

        if (direction == "sunrise") {
                return(ss[1,1])     
        } else {
                return(ss[1,2])
        }       
}

Когда я запускаю функцию для одного входа, я получаюожидаемый результат:

sunrise.set2(41.2, -73.2, "2018-12-09 07:34:0", timezone="EST", 
    direction = "sunset", num.days = 1)
[1] "2018-12-09 16:23:46 EST"

Однако, когда я пытаюсь сделать это на объекте кадра данных, чтобы изменить его в новом столбце, например:

df <- df %>% 
    mutate(set = sunrise.set2(Latitude, Longitude, LocalDateTime, timezone="UTC", num.days = 1, direction = "sunset"))

Я получаю следующую ошибку:

Error in mutate_impl(.data, dots) : 
  Evaluation error: 'from' must be of length 1.

dput моего df ниже.Я подозреваю, что не делаю что-то правильно, чтобы правильно векторизовать свою функцию, но я не уверен, что.

Спасибо

dput (df):

structure(list(Latitude = c(20.666, 20.676, 20.686, 20.696, 20.706, 
20.716, 20.726, 20.736, 20.746, 20.756, 20.766, 20.776), Longitude = c(-156.449, 
-156.459, -156.469, -156.479, -156.489, -156.499, -156.509, -156.519, 
-156.529, -156.539, -156.549, -156.559), LocalDateTime = structure(c(1534318440, 
1534404840, 1534491240, 1534577640, 1534664040, 1534750440, 1534836840, 
1534923240, 1535009640, 1535096040, 1535182440, 1535268840), class = c("POSIXct", 
"POSIXt"), tzone = "UTC")), .Names = c("Latitude", "Longitude", 
"LocalDateTime"), row.names = c(NA, -12L), class = c("tbl_df", 
"tbl", "data.frame"), spec = structure(list(cols = structure(list(
    Latitude = structure(list(), class = c("collector_double", 
    "collector")), Longitude = structure(list(), class = c("collector_double", 
    "collector")), LocalDateTime = structure(list(format = "%m/%d/%Y %H:%M"), .Names = "format", class = c("collector_datetime", 
    "collector"))), .Names = c("Latitude", "Longitude", "LocalDateTime"
)), default = structure(list(), class = c("collector_guess", 
"collector"))), .Names = c("cols", "default"), class = "col_spec"))

1 Ответ

0 голосов
/ 10 декабря 2018

Проблема действительно в том, что ваша функция в том виде, в каком она есть сейчас, не векторизована, она ломается, если вы даете ей более одного значения.Обходной путь (как предположил Сулиман) использует rowwise() или вариант apply, но это даст вашей функции много ненужной работы.

Так что лучше сделать ее векторизованной, так как maptools::sunrisetтакже векторизовано.Первое предложение: отладьте или перепишите его с векторами в качестве входных данных, а затем вы легко увидите строки, где происходит что-то неожиданное.Давайте посмотрим на это построчно, я прокомментировал ваши строки, где я заменил их чем-то другим:

library(maptools)
library(tidyverse)

# sunrise.set2 <- function (lat, long, date, timezone = "UTC", direction = c("sunrise", "sunset"), num.days = 1) 
sunrise.set2 <- function (lat, long, date, timezone = "UTC", direction = c("sunrise", "sunset")
# Why an argument saying how many days? You have the length of your dates
{
        #lat.long <- matrix(c(long, lat), nrow = 1)
        lat.long <- cbind(lon, lat)
        day <- as.POSIXct(date, tz = timezone)
        # sequence <- seq(from = day, length.out = num.days, by = "days") # Your days object is fine
        sunrise <- sunriset(lat.long, day, direction = "sunrise", 
                            POSIXct = TRUE)
        sunset <- sunriset(lat.long, day, direction = "sunset", 
                           POSIXct = TRUE)
        # I've replaced sequence with day here
        ss <- data.frame(sunrise, sunset)
        ss <- ss[, -c(1, 3)]
        colnames(ss) <- c("sunrise", "sunset")

        if (direction == "sunrise") {
                #return(ss[1,1])
                return(ss[,1])
        } else {
                #return(ss[1,2])
                return(ss[,2])
        }       
}

Но, глядя на вашу функцию, я думаю, что все еще много дополнительной работы, которая неНе для какой-либо цели.

  • Вы рассчитываете как восход, так и закат, только для использования одного из них.И вы можете просто передать один свой аргумент направления, даже не глядя на него.
  • Полезно ли запрашивать отдельную дату и часовой пояс?Когда ваши пользователи дают вам POSIXt -объект, часовой пояс включается.И хорошо, если вы можете ввести строку в качестве даты, но это работает, только если она в правильном формате.Чтобы было проще, я бы просто попросил POSIXct в качестве ввода (что есть в вашем примере-data.frame)
  • Почему вы делаете data.frame и присваиваете имена перед возвратом?Как только вы выполняете поднабор, все снова сбрасывается.

Это означает, что ваша функция может быть намного короче:

sunrise.set2 <- function(lat, lon, date, direction = c("sunrise", "sunset")) {
  lat.long <- cbind(lon, lat)
  sunriset(lat.long, date, direction=direction, POSIXct.out=TRUE)[,2]
}

Если вы не можете контролировать свой вводвам может понадобиться добавить несколько проверок, но обычно я считаю наиболее полезным сосредоточиться на том, чего вы хотите достичь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...