我试图利用data.table
和ggplot2
功能的高级技巧创建一个简单而强大的功能,自动绘制(在一个图像中!)所有列(y)任意data.table
作为输入列(x)的函数,由列(k)进行优化调整 - 这样我们就可以使用单行快速可视化所有数据列:
dt <- data.table(diamonds[1:100,])[order(carat),cut:=as.character(cut)]
plotAllXYbyZ(dt)
plotAllXYbyZ(dt, x="carat", k="color")
plotAllXYbyZ(dt, x=1, y=c(2,8:10), k=3)
澄清:挑战在于列可以是任何一种类型(数字,字符或因子)。我们想要一个自动处理这个功能的功能。 - 即它应该能够使用melt和ggplot绘制所有请求的列,正如我在下面的答案中尝试的那样。
更新:我的代码发布在答案中。它的功能(即显示所需的图)。但它有一个问题,即:它修改原始data.table。 - 为了解决这个问题,我在这里提出了一个新问题:Don't want original data.table to be modified when passed to a function
答案 0 :(得分:1)
我希望这适合你:
plotAllXYbyZ <- function(dt, x, y, z) {
# to make sure all columns to be melted for ploting are numerical
dt[, (y):= lapply(.SD, function(x) {as.numeric(as.character(x))}), .SDcols = y]
dts <- melt(dt, id = c(x,z), measure = y)
ggplot(dts, aes_string(x = colnames(dt)[x], y = "value", colours = colnames(dt)[z])) +
geom_line() + facet_wrap(~ variable)
}
dt <- data.table(mtcars)
plotAllXYbyZ(dt, x=1, y=3:10, z=2)
答案 1 :(得分:0)
感谢上面的评论,下面是实现所需输出的代码。 - 下图显示了这些生产线的产出:
dtDiamonds <- data.table(diamonds[1:100,])[order(carat),cut:=as.character(cut)]
plotAllXYbyZ(dtDiamonds);
plotAllXYbyZ(dtDiamonds, x="carat", k="color")
plotAllXYbyZ(dtDiamonds, x=1, y=c(2,8:10), k=3)
为了做到这一点,我必须引入一个函数将所有内容转换为数字。
唯一剩下的问题是原始dtDiamonds
被修改了! - 因为':='。要解决此问题,我在此处发布了一个单独的问题:为了解决此问题,我在此处提出了一个新问题:Don't want original data.table to be modified when passed to a function。更新:现在使用<-copy(dt)
代替<-dt
来解决此问题。
# A function to convert factors and characters to numeric.
my.as.numeric <- function (x) {
if (is.factor(x)) {
if (T %in% is.na(as.numeric(as.character(x)))) # for factors like "red", "blue"
return (as.numeric(x))
else # for factors like "20", "30", ...
return (as.numeric(as.character(x))) # return: 20, 30, ...
}
else if (is.character(x)) {
if (T %in% is.na(as.numeric(x)))
return (as.numeric(as.ordered(x)))
else # the same: for character variables like "20", "30", ...
return (as.numeric(x)) # return: 20, 30, ... Otherwise, convert them to factor
return (x)
}
}
plotAllXYbyZ <- function(.dt, x=NULL, y=NULL, k=NULL) {
dt <- copy(.dt) # NB: If copy is not used, the original data.table will get modified !
if (is.numeric(x)) x <- names(dt)[x]
if (is.numeric(y)) y <- names(dt)[y]
if (is.numeric(k)) k <- names(dt)[k]
if (is.null(x)) x <- names(dt)[1]
"%wo%" <- function(x, y) x[!x %in% y]
if (is.null(y)) y <- names(dt) %wo% c(x,k)
# to make sure all columns to be melted for plotting are numerical
dt[, (y):= lapply(.SD, function(x) {my.as.numeric(x)}), .SDcols = y]
ggplot(melt(dt, id=c(x,k), measure = y)) +
geom_step(aes(get(x),value,col=variable)) +
ifelse (is.null(k), list(NULL), list(facet_wrap(~get(k))) ) +
labs(x=x, title=sprintf("variable = F (%s | %s)", x, k))
}
[] [] 3