gesistsa / rio

🐟 A Swiss-Army Knife for Data I/O
http://gesistsa.github.io/rio/
600 stars 76 forks source link

rio export fails for duration variable with label attribute, haven-export works #433

Open hsbizahlenzauber opened 3 months ago

hsbizahlenzauber commented 3 months ago

MWE

rio export fails for duration variable with label attribute, haven-export works

library("lubridate") library("rio") library("haven")

creating a variable of class period

duration <- seconds_to_period(duration(hours=26000))

creating data frame

data <- data.frame(duration)

setting variable label as attribute

without this attribute, everything works as expected

attr(data$duration, "label") <- "Duration"

export with haven

no error message

haven::write_sav(data, path="testHAVEN.sav")

export with rio

Error in new_labelled():

! x must be a numeric or a character vector.

rio::export(data, file="testRIO.sav")

chainsawriot commented 3 months ago

@hsbizahlenzauber Thank you for reporting this. I can reproduce this.

library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#> 
#>     date, intersect, setdiff, union
library(rio)

duration <- seconds_to_period(duration(hours = 26000))

#creating data frame

duration_data <- data.frame(duration)
attr(duration_data$duration, "label") <- "Duration"
haven::write_sav(duration_data, path = tempfile(fileext = ".sav"))

rio::export(duration_data, file = tempfile(fileext = ".sav"))
#> Error in `new_labelled()`:
#> ! `x` must be a numeric or a character vector.

Created on 2024-06-20 with reprex v2.1.0

And this is where it fails.

https://github.com/gesistsa/rio/blob/588971f7c5558805c1e7efc2f89cc0e1f245a4c7/R/standardize_attributes.R#L38-L58

TBH, I have to study this bunch of code to derive a solution, because I am not super familiar with these variable labeling code. It might take some time.

chainsawriot commented 3 months ago

755cdecd561fa7adb5dfda49e4d9339ca4924684 #268

chainsawriot commented 3 months ago

@hsbizahlenzauber You know that haven (the package under the hood) does not actually support the Period class of lubridate, right?

library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#> 
#>     date, intersect, setdiff, union
library(rio)

duration <- seconds_to_period(duration(hours = 26000))

#creating data frame

duration_data <- data.frame(duration)
duration_data
#>         duration
#> 1 1083d 8H 0M 0S

attr(duration_data$duration, "label") <- "Duration"
haven::write_sav(duration_data, path = x <- tempfile(fileext = ".sav"))

haven::read_sav(x)
#> # A tibble: 1 × 1
#>   duration
#>      <dbl>
#> 1        0

Created on 2024-06-20 with reprex v2.1.0

hsbizahlenzauber commented 3 months ago

@chainsawriot Many thanks for taking care of this and for the tip. I have to admit that I'm not really familiar with the details of different data types. I report when I notice something and I'm very glad that there are people who deal with it.