我需要"转换"将data.frame
个对象转换为纯文本(如控制台的print
输出。
到目前为止,我创建了以下函数(使用stringr
包),但我想知道是否存在已实现的函数或更有效的方法:
toString.data.frame = function(object, ...) {
maxLen = max(
stringr::str_length(apply(object, c(1,2), as.character)),
stringr::str_length(names(object))
);
# data-frame to character matrix
txt = apply(object, c(1,2), stringr::str_pad, width=maxLen+5, side="left");
# concatenate the columns
txt = apply(txt, 1, paste, collapse="");
# concatenate the rows
txt = paste(txt, collapse="\n");
# add column names
txt = paste( # concatenate header and body
paste( # concatenate all the headers
stringr::str_pad( # add 5 spaces on the left of each header
stringr::str_pad(names(object), width=maxLen, side="right") # fill each header
, width=maxLen+5, side="left")
, collapse="")
, txt
, sep="\n");
return(txt);
}
我添加了一些可运行的代码以及一个输出示例(每个输出行由" |"分隔)
df = data.frame(hello=rnorm(1:15), world=rnorm(1:15));
cat(toString(object), "\n");
| a b |
| 0.217785930312173 1.35892062758937|
| -0.0529272009376736 -1.3537444650507|
| -0.0914533595349014 -0.283164123247757|
| 0.209099248751634 -0.994596208802379|
| 1.41207193727609 0.754568758899429|
| 0.0271570788346636 0.722728545001598|
| 1.09160395973882 -0.466194711071017|
| -0.676012596015548 0.247534965195453|
| 0.36022565974381 -0.318822054653857|
| 0.330251755314496 -0.379818935427323|
| 1.29858423625996 0.393100959746072|
| 1.79061048596737 0.124484229714237|
| -0.636849202004066 -1.48651181772674|
| 1.08795175312078 0.231693241998673|
| -0.810214549466222 -0.753200696904484|
答案 0 :(得分:3)
我认为使用sink
和textConnection
会更简单,并且会为您的效果提供一些手动格式化。
df = data.frame(hello=rnorm(1:15), world=rnorm(1:15));
tc <- textConnection("str", "w")
sink(tc) # divert output to tc connection
print(df) # print in str string instead of console
sink() # set the output back to console
close(tc) # close connection
str <- substr(str,floor(length(str)/10)+3,nchar(str[1])) # we get rid of the row numbers that come with print
str <- paste0("| ",str,"|",collapse="\n") # we build a proper unique string with your pipes and new lines
cat(str)
# | hello world|
# | 1.35547838 0.69280925|
# | 0.61364635 1.84942722|
# | -0.23441769 0.10034022|
# | 1.73325659 -0.22303366|
# | -0.65542783 -0.47574465|
# | -0.87341058 -0.63579176|
# | 0.04449579 0.36899672|
# | -1.00486219 1.25508269|
# | -0.23235707 1.18740340|
# | -0.46296889 0.88100960|
# | 0.52494728 0.20217947|
# | 0.94017525 0.01272363|
# | -0.09997728 0.22612848|
# | -0.04388133 -0.49271157|
# | -1.09953287 -0.27971771|
答案 1 :(得分:2)
在看了print.data.frame
函数后,我敢说下面的内容可能是更好的解决方案(更好的格式化,并且几乎与经过良好测试的bult-in函数的代码相同)
toString.data.frame = function (object, ..., digits=NULL, quote=FALSE, right=TRUE, row.names=TRUE) {
nRows = length(row.names(object));
if (length(object)==0) {
return(paste(
sprintf(ngettext(nRows, "data frame with 0 columns and %d row", "data frame with 0 columns and %d rows")
, nRows)
, "\\n", sep = "")
);
} else if (nRows==0) {
return(gettext("<0 rows> (or 0-length row.names)\\n"));
} else {
# get text-formatted version of the data.frame
m = as.matrix(format.data.frame(object, digits=digits, na.encode=FALSE));
# define row-names (if required)
if (isTRUE(row.names)) {
rowNames = dimnames(object)[[1]];
if(is.null(rowNames)) {
# no row header available -> use row numbers
rowNames = as.character(1:NROW(m));
}
# add empty header (used with column headers)
rowNames = c("", rowNames);
}
# add column headers
m = rbind(dimnames(m)[[2]], m);
# add row headers
m = cbind(rowNames, m);
# max-length per-column
maxLen = apply(apply(m, c(1,2), stringr::str_length), 2, max, na.rm=TRUE);
# add right padding
## t is needed because "If each call to FUN returns a vector of length n, then apply returns an array of dimension c(n, dim(X)[MARGIN])"
m = t(apply(m, 1, stringr::str_pad, width=maxLen, side="right"));
m = t(apply(m, 1, stringr::str_pad, width=maxLen+3, side="left"));
# merge columns
m = apply(m, 1, paste, collapse="");
# merge rows (and return)
return(paste(m, collapse="\n"));
}
}