Arnaud Mosnier
2010-Jan-13 14:01 UTC
[R] column width in .dbf files using write.dbf ... to be continued
Dear UseRs,
I did not have any answer to my previous message ("Is there a way to define
"manually" columns width when using write.dbf function from the
library
foreign ?"), so I tried to modify write.dbf function to do what I want.
Here is my modified version :
write.dbfMODIF <- function (dataframe, file, factor2char = TRUE, max_nchar
254, width = d)
{
allowed_classes <- c("logical", "integer",
"numeric", "character",
"factor", "Date")
if (!is.data.frame(dataframe))
dataframe <- as.data.frame(dataframe)
if (any(sapply(dataframe, function(x) !is.null(dim(x)))))
stop("cannot handle matrix/array columns")
cl <- sapply(dataframe, function(x) class(x[1L]))
asis <- cl == "AsIs"
cl[asis & sapply(dataframe, mode) == "character"] <-
"character"
if (length(cl0 <- setdiff(cl, allowed_classes)))
stop("data frame contains columns of unsupported class(es) ",
paste(cl0, collapse = ","))
m <- ncol(dataframe)
DataTypes <- c(logical = "L", integer = "N", numeric
= "F",
character = "C", factor = if (factor2char) "C" else
"N",
Date = "D")[cl]
for (i in seq_len(m)) {
x <- dataframe[[i]]
if (is.factor(x))
dataframe[[i]] <- if (factor2char)
as.character(x)
else as.integer(x)
else if (inherits(x, "Date"))
dataframe[[i]] <- format(x, "%Y%m%d")
}
precision <- integer(m)
scale <- integer(m)
dfnames <- names(dataframe)
for (i in seq_len(m)) {
nlen <- nchar(dfnames[i], "b")
x <- dataframe[, i]
if (is.logical(x)) {
precision[i] <- 1L
scale[i] <- 0L
}
else if (is.integer(x)) {
rx <- range(x, na.rm = TRUE)
rx[!is.finite(rx)] <- 0
if (any(rx == 0))
rx <- rx + 1
mrx <- as.integer(max(ceiling(log10(abs(rx)))) +
3L)
precision[i] <- min(max(nlen, mrx), 19L)
scale[i] <- 0L
}
else if (is.double(x)) {
precision[i] <- 19L
rx <- range(x, na.rm = TRUE)
rx[!is.finite(rx)] <- 0
mrx <- max(ceiling(log10(abs(rx))))
scale[i] <- min(precision[i] - ifelse(mrx > 0L, mrx +
3L, 3L), 15L)
}
else if (is.character(x)) {
if (width == "d") {
mf <- max(nchar(x[!is.na(x)], "b"))
p <- max(nlen, mf)
if (p > max_nchar)
warning(gettext("character column %d will be truncated
to %d bytes",
i, max_nchar), domain = NA)
precision[i] <- min(p, max_nchar)
scale[i] <- 0L
} else {
if (width > max_nchar)
warning(gettext("character column %d will be truncated
to %d bytes",
i, max_nchar), domain = NA)
precision[i] <- min(width, max_nchar)
}
}
else stop("unknown column type in data frame")
}
if (any(is.na(precision)))
stop("NA in precision")
if (any(is.na(scale)))
stop("NA in scale")
invisible(.Call(DoWritedbf, as.character(file), dataframe,
as.integer(precision), as.integer(scale), as.character(DataTypes)))
}
However, when I wanted to use this function ... it does not find the
DoWritedbf function that is called in the last lines (a function written in
C).
Is there a way to temporally replace the original write.dbf function by this
one in the foreign package ?
Thanks,
Arnaud
R version 2.10.0 (2009-10-26)
i386-pc-mingw32
[[alternative HTML version deleted]]
Luiz Max Carvalho
2012-Oct-11 12:31 UTC
[R] column width in .dbf files using write.dbf ... to be continued
Old topic... An answer may be useful for someone else, though... Just do : > environment(write.dbfMODIF)<-environment(foreign::write.dbf ) and it should be good to go. Cheers, -- View this message in context: http://r.789695.n4.nabble.com/column-width-in-dbf-files-using-write-dbf-to-be-continued-tp1013017p4645841.html Sent from the R help mailing list archive at Nabble.com.