簡體   English   中英

使用dplyr :: mutate計算適用於數據框的日出函數?

[英]Calculate sunrise function that works with dataframe with dplyr::mutate?

我嘗試將其應用於數據框以在新列中進行變異時編寫的函數遇到麻煩

我想在數據框中添加一列,以根據現有的緯度,經度和日期列來計算所有行的日出/日落時間。 日出/日落計算源自maptools軟件包中的“ sunriseset”函數。

下面是我的功能:

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"

但是,當我嘗試在dataframe對象上執行此操作以在新列中進行變異時,如下所示:

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.

我df的dput在下面。 我懷疑為了正確向量化我的功能,我沒有做正確的事,但是我不確定是什么。

謝謝

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"))

問題確實是您的函數現在沒有被向量化,如果您給它提供多個值,它就會中斷。 一種解決方法(如rowwise()建議的)使用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 ,我只要求輸入POSIXct (在您的example-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]
}

如果您無法控制自己的輸入,則可能需要添加一些檢查,但是通常我發現,專注於您要完成的事情最有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM