Skip to content

Commit

Permalink
Support for objects from 'tibble' and 'haven'
Browse files Browse the repository at this point in the history
  • Loading branch information
melff committed Nov 18, 2019
1 parent 98a4001 commit 5894320
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 23 deletions.
4 changes: 2 additions & 2 deletions pkg/DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Package: memisc
Type: Package
Title: Management of Survey Data and Presentation of Analysis Results
Version: 0.99.19
Date: 2019-11-09
Date: 2019-11-17
Author: Martin Elff (with contributions from Christopher N. Lawrence, Dave Atkins, Jason W. Morgan, Achim Zeileis)
Maintainer: Martin Elff <memisc@elff.eu>
Description: An infrastructure for the management of survey data including
Expand All @@ -16,7 +16,7 @@ License: GPL-2
LazyLoad: Yes
Depends: R (>= 3.3.0), lattice, stats, methods, utils, MASS
Suggests: splines, knitr, rmarkdown, sandwich
Enhances: AER, car, eha, lme4, ordinal, simex
Enhances: AER, car, eha, lme4, ordinal, simex, tibble, haven
Imports: grid, repr
VignetteBuilder: knitr
URL: http://www.elff.eu/software/memisc/,http://github.com/melff/memisc/
Expand Down
6 changes: 6 additions & 0 deletions pkg/NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -419,3 +419,9 @@ export(withGroups,withinGroups)

export(Reshape)
export(spss.file)

export(as_tibble.data.set)
# S3method("as_tibble",data.set)
# exportMethods(as_tibble)
export(as_haven)
exportMethods(as_haven)
27 changes: 17 additions & 10 deletions pkg/R/dataset-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -544,16 +544,23 @@ rbind.data.set <- function(...,deparse.level=1){

dsView <- function(x){

title <- paste("Data set:", deparse(substitute(x))[1])

Data <- lapply(x@.Data,format,justify="left")
document <- x@document
row.names <- x@row_names
.names <- x@names
frame <- structure(Data,row.names=row.names,names=x@names,
class="data.frame")
View.call <- call("View",x=frame,title=title)
eval(View.call,globalenv())
title <- paste("Data set:", deparse(substitute(x))[1])

Data <- lapply(x@.Data,format,justify="left")

document <- x@document
row.names <- x@row_names
.names <- x@names
frame <- structure(Data,row.names=row.names,names=x@names,
class="data.frame")
for(n in names(frame)){
d <- description(x[[n]])
if(length(d))
attr(frame[[n]],"label") <- d
}

View.call <- call("View",x=frame,title=title)
eval(View.call,globalenv())
#View(x=frame,title=title)
# do.call("View",list(x=frame,title=title))
}
Expand Down
57 changes: 46 additions & 11 deletions pkg/R/item-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ setMethod("as.item","numeric",function(x,
measurement <- if(length(measurement)) match.arg(measurement,c("nominal","ordinal","interval","ratio"))
else if(length(value.labels) && !length(measurement)) "nominal" else "interval"
annotation <- new("annotation",structure(as.character(annotation),names=names(annotation)))
label <- attr(x,"label")
if("description" %nin% names(annotation) && length(label))
annotation["description"] <- label
cl <- paste(storage.mode(x),"item",sep=".")
new(cl,
x,
Expand All @@ -85,12 +88,20 @@ setMethod("as.item","numeric",function(x,

setMethod("as.item","logical",function(x,...) {
y <- as.integer(x)
attr(y,"annotation") <- attr(x,"annotation")
annotation <- attr(x,"annotation")
label <- attr(x,"label")
if("description" %nin% names(annotation) && length(label))
annotation["description"] <- label
attr(y,"annotation") <- annotation
as.item(y,...)
})
setMethod("as.item","factor",function(x,...){
y <- as.integer(x)
attr(y,"annotation") <- attr(x,"annotation")
annotation <- attr(x,"annotation")
label <- attr(x,"label")
if("description" %nin% names(annotation) && length(label))
annotation["description"] <- label
attr(y,"annotation") <- annotation
y <- as.item(y,
labels=new("value.labels",levels(x),values=seq_along(levels(x))),
measurement="nominal",
Expand All @@ -100,7 +111,11 @@ setMethod("as.item","factor",function(x,...){
})
setMethod("as.item","ordered",function(x,...){
y <- as.integer(x)
attr(y,"annotation") <- attr(x,"annotation")
annotation <- attr(x,"annotation")
label <- attr(x,"label")
if("description" %nin% names(annotation) && length(label))
annotation["description"] <- label
attr(y,"annotation") <- annotation
y <- as.item(y,
labels=new("value.labels",levels(x),values=seq_along(levels(x))),
measurement="ordinal",
Expand Down Expand Up @@ -137,6 +152,9 @@ setMethod("as.item","character",function(x,
measurement <- if(length(measurement)) match.arg(measurement,c("nominal","ordinal"))
else "nominal"
annotation <- new("annotation",structure(as.character(annotation),names=names(annotation)))
label <- attr(x,"label")
if("description" %nin% names(annotation) && length(label))
annotation["description"] <- label
new("character.item",x,
value.labels=value.labels,
value.filter=value.filter,
Expand Down Expand Up @@ -253,7 +271,7 @@ as.data.frame.integer.item <- function (x, row.names = NULL, optional = FALSE, .
x <- if(is.ordinal(x)) as.ordered(x)
else if(is.nominal(x)) as.factor(x)
else as.vector(x)

value <- list(x)
if (!optional)
names(value) <- nm
Expand All @@ -267,6 +285,9 @@ setMethod("as.vector","item",function(x,mode = "any"){
x <- callNextMethod()
if(mode=="any") mode <- storage.mode(x)
x[ism] <- as.vector(NA,mode=mode)
d <- description(x)
if(length(d))
attr(x,"label") <- d
x
})

Expand All @@ -291,6 +312,9 @@ setMethod("as.ordered","item.vector",function(x){
f <- ordered(x@.Data,levels=values,labels=labels)
if(length(attr(x,"contrasts")))
attr(f,"contrasts") <- contrasts(x)
d <- description(x)
if(length(d))
attr(f,"label") <- d
f
})

Expand All @@ -312,17 +336,28 @@ setMethod("as.factor","item.vector",function(x){
f <- factor(x@.Data,levels=values,labels=labels)
if(length(attr(x,"contrasts")))
contrasts(f) <- contrasts(x)
d <- description(x)
if(length(d))
attr(f,"label") <- d
f
})

setMethod("as.character","item.vector",function(x,use.labels=TRUE,...){
if(use.labels && length(vl <- labels(x))){
i <- match(x,vl@values)
y <- vl@.Data[i]
y[is.na(y)] <- as.character(x@.Data[is.na(y)])
y
}
else as.character(x@.Data)
d <- description(x)
if(use.labels && length(vl <- labels(x))){
i <- match(x,vl@values)
y <- vl@.Data[i]
y[is.na(y)] <- as.character(x@.Data[is.na(y)])
if(length(d))
attr(y,"label") <- d
y
}
else {
y <- as.character(x@.Data)
if(length(d))
attr(y,"label") <- d
y
}
})


Expand Down
72 changes: 72 additions & 0 deletions pkg/R/tibbles.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
setGeneric("prep_for_tibble",function(x,...)standardGeneric("prep_for_tibble"))
setMethod("prep_for_tibble",signature(x="item.vector"),function(x,...)
prep_for_tibble_item_vector(x))

prep_for_tibble_item_vector <- function(x,...){
y <- if(inherits(x,"character.item")) as.character(x)
else if(is.ordinal(x)) as.ordered(x)
else if(is.nominal(x)) as.factor(x)
else as.vector(x)
d <- description(x)
if(length(d))
attr(y,"label") <- d
return(y)
}

as_tibble.data.set <- function(x, ...){
y <- lapply(x@.Data,
prep_for_tibble_item_vector)
names(y) <- names(x)
attr(y,"row.names") <- x@row_names
class(y) <- c("tbl_df","tbl","data.frame")
return(y)
}

setOldClass("haven_labelled")
setMethod("as.item",signature(x="haven_labelled"),function(x,...){
annotation <- c(description=attr(x,"label"))
labels <- attr(x,"labels")
class(x) <- NULL
as.item(x,labels=labels,
annotation=annotation)
})

setOldClass("haven_labelled_spss")
setMethod("as.item",signature(x="haven_labelled_spss"),function(x,...){
annotation <- c(description=attr(x,"label"))
labels <- attr(x,"labels")
mis_range <- attr(x,"na_range")
mis_values <- attr(x,"na_values")
class(x) <- NULL
value_filter <- new("missing.values",
filter=mis_values,
range=mis_range)
as.item(x,labels=labels,
annotation=annotation,
value.filter=value_filter)
})

setGeneric("as_haven",function(x,...)standardGeneric("as_haven"))
setMethod("as_haven",signature(x="data.set"),function(x,user_na=FALSE,...){
y <- lapply(x@.Data,as_haven,user_na=user_na,...)
names(y) <- names(x)
attr(y,"row.names") <- x@row_names
class(y) <- c("tbl_df","tbl","data.frame")
return(y)
})
setMethod("as_haven",signature(x="item.vector"),function(x,user_na=FALSE,...){
y <- x@.Data
attr(y,"label") <- description(x)
attr(y,"labels") <- as.vector(labels(x))
ms <- missing.values(x)
if(user_na && length(ms)){
attr(y,"na_values") <- ms@filter
attr(y,"na_range") <- ms@range
class(y) <- "haven_labelled_spss"
} else {
ism <- is.missing(x)
y[ism] <- NA
class(y) <- "haven_labelled"
}
return(y)
})
47 changes: 47 additions & 0 deletions pkg/man/tibbles.Rd
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
\name{tibbles}
\alias{as_tibble.data.set}
\alias{as.item,haven_labelled-method}
\alias{as.item,haven_labelled_spss-method}
\alias{as_haven}
\alias{as_haven,data.set-method}
\alias{as_haven,item.vector-method}
\title{Interface to packages 'tibble' and 'haven'}
\description{
A \code{as_tibble} method (\code{as_table.data.set}) allows to transform \code{"data.set"} objects
into objects of class \code{"tbl_df"} as defined by the package
"tibble".

\code{as.item} methods for objects of classes \code{"haven_labelled"}
and \code{"have_labelled_spss"} allow to transform a "tibble" imported
using \code{read_dta}, \code{read_spss}, etc. from the package "haven"
into an object of class \code{"data.set"}.

\code{as_haven} can be used to transform \code{"data.set"} objects
into objects of class \code{"tbl_df"} with that additional information
that objects imported using the "haven" package usually have, i.e.
variable labels and value labels (as the \code{"label"} and
\code{"labels"} attributes of the columns).
}
\usage{
as_tibble.data.set(x,\dots)
\S4method{as.item}{haven_labelled}(x,\dots)
\S4method{as.item}{haven_labelled_spss}(x,\dots)
as_haven(x,\dots)
\S4method{as_haven}{data.set}(x,user_na=FALSE,\dots)
\S4method{as_haven}{item.vector}(x,user_na=FALSE,\dots)
}
\arguments{
\item{x}{for \code{as_tibble.data.set} and \code{as_haven}, an object
of class \code{"data.set"}; for \code{as.item}, an object of class
\code{"haven_labelled"} or \code{"haven_labelled_spss"}.}
\item{user_na}{logical; if \code{TRUE} then the resulting vectors
have an \code{"na_values"} and/or \code{"na_range"} attribute.}
\item{\dots}{further arguments, passed through to other the the
\code{as_tibble} method for lists, or ignored.}
}
\value{
\code{as_tibble.data.set} and the \code{"data.set"}-method of
\code{as_haven} return a "tibble". The \code{"item.vector"}-method
(which is for internal use only) returns a vector with S3 class either
\code{"haven_labelled"} or \code{"haven_labelled_spss"}.
}

0 comments on commit 5894320

Please sign in to comment.