如何在R中绘制数据框的所有列

98
数据框有n列,我想为每一列获取一个图表。
我是新手,对R语言不太熟悉,但我找到了两种解决方案。
第一种方法可以实现,但它不会打印列名(而我需要它们!)。
data <- read.csv("sample.csv",header=T,sep=",")
for ( c in data ) plot( c, type="l" )

第二个更好,因为它打印列名:
data <- read.csv("sample.csv",header=T,sep=",")
for ( i in seq(1,length( data ),1) ) plot(data[,i],ylab=names(data[i]),type="l")

从R语言的角度来看,是否有更好的解决方案?


2
在你的第二个例子中,我会这样初始化循环 for(i in seq_along(dat)),而且我也不会把我的数据称为 data - Gavin Simpson
3
你的 read.csv 可以简化为 read.csv("sample.csv"),因为其他参数只是被设置为它们的默认值。 - G. Grothendieck
11个回答

107
< p > ggplot2包需要一些学习,但结果看起来非常好,您可以获得漂亮的图例,以及许多其他漂亮的功能,而无需编写太多代码。 < /p >
require(ggplot2)
require(reshape2)
df <- data.frame(time = 1:10,
                 a = cumsum(rnorm(10)),
                 b = cumsum(rnorm(10)),
                 c = cumsum(rnorm(10)))
df <- melt(df ,  id.vars = 'time', variable.name = 'series')

# plot on same grid, each series colored differently -- 
# good if the series have same scale
ggplot(df, aes(time,value)) + geom_line(aes(colour = series))

# or plot on different plots
ggplot(df, aes(time,value)) + geom_line() + facet_grid(series ~ .)

enter image description here enter image description here


1
很好的回答,但你为什么需要reshape呢? - eliasah
谢谢@VerenaHaunschmid,我后来已经弄明白了 :-) - eliasah
需要使用melt。 - Bruce_Warrior

48

有一种非常简单的方法可以使用不同面板或相同面板绘制数据框中的所有列:

plot.ts(data)

这将产生以下结果(其中X1 - X4是列名):

enter image description here

查看?plot.ts以获取所有选项。

如果您想更精细地控制绘图函数而不使用循环,也可以尝试如下操作:

par(mfcol = c(ncol(data), 1))
Map(function(x,y) plot(x, main =y), data, names(data))

谢谢,即使它与时间序列有关,我认为这可以帮助我掌握我的数据。我喜欢一行代码! - Alessandro Jacopson
7
一个小提示:当添加'plot.type=c("single")'时,您的系列将绘制在单个图表上,而不是分开的框中:`data <- data.frame(x=c(rnorm(10)),y=c(rnorm(10)),z=c(rnorm(10)))plot.ts(data,plot.type=c("single"),lty=1:3)` - Geek On Acid
@GeekOnAcid +1,非常感谢您提供“single”的提示。 - Alessandro Jacopson
如果你要使用 single,你还应该添加:col=rainbow(ncol(my.data)) 或类似的内容以保持线条的可读性。 - bright-star

15
你可以通过转换成lapplysapplyapply调用来跳过一些步骤(我看到@jonw展示了一种方法)。除此之外,你已经有了完全可接受的代码。 如果这些都是时间序列或类似的数据,则以下内容可能是一个合适的替代方案,它将每个系列绘制在单个绘图区域的自己面板中。我们使用zoo包,因为它非常擅长处理有序数据。
require(zoo)
set.seed(1)
## example data
dat <- data.frame(X = cumsum(rnorm(100)), Y = cumsum(rnorm(100)),
                  Z = cumsum(rnorm(100)))
## convert to multivariate zoo object
datz <- zoo(dat)
## plot it
plot(datz)
哪个会产生: zoo绘图功能示例

14

我很惊讶没有人提到matplot。如果您不需要将每条线绘制在单独的轴上,它非常方便。 只需一个命令:

matplot(y = data, type = 'l', lty = 1)

使用 ?matplot 查看所有选项。

要添加图例,您可以设置颜色调色板,然后添加它:

mypalette = rainbow(ncol(data))
matplot(y = data, type = 'l', lty = 1, col = mypalette)
legend(legend = colnames(data), x = "topright", y = "topright", lty = 1, lwd = 2, col = mypalette)

matlab.dark.palette是什么,它来自哪里? - Alessandro Jacopson
1
@AlessandroJacopson 这是我通常使用的调色板函数。它来自于 hyperSpec 包。但在这里最好使用更为常见的函数,所以我将其改为了 rainbow。如果您不熟悉调色板函数,请查看 ?rainbow。对于造成的困惑,我感到抱歉。 - Rustam Guliev

9
使用以上一些技巧(特别是感谢@daroczig提供的names(df)[i]形式),此函数会打印数值变量的直方图和因子变量的条形图。这是探索数据框的好开始:
par(mfrow=c(3,3),mar=c(2,1,1,1)) #my example has 9 columns

dfplot <- function(data.frame)
{
  df <- data.frame
  ln <- length(names(data.frame))
  for(i in 1:ln){
    mname <- substitute(df[,i])
      if(is.factor(df[,i])){
        plot(df[,i],main=names(df)[i])}
        else{hist(df[,i],main=names(df)[i])}
  }
}

最好的祝福,Mat.

7

遗憾的是,ggplot2并没有提供一种不需要将您的数据转换为长格式(轻松地)完成此操作的方式。你可以尝试与它作斗争,但数据转换会更容易。这里有所有的方法,包括 melt (来自 reshape2)、gather (来自 tidyr) 以及 pivot_longer (来自 tidyr): 从宽格式重构数据框架至长格式

以下是使用 pivot_longer 的简单示例:

> df <- data.frame(time = 1:5, a = 1:5, b = 3:7)
> df
  time a b
1    1 1 3
2    2 2 4
3    3 3 5
4    4 4 6
5    5 5 7

> df_wide <- df %>% pivot_longer(c(a, b), names_to = "colname", values_to = "val")
> df_wide
# A tibble: 10 x 3
    time colname   val
   <int> <chr>   <int>
 1     1 a           1
 2     1 b           3
 3     2 a           2
 4     2 b           4
 5     3 a           3
 6     3 b           5
 7     4 a           4
 8     4 b           6
 9     5 a           5
10     5 b           7

如您所见,pivot_longer 将所选列名放在 names_to(默认为“name”)指定的位置,并将长的值放入 values_to(默认为“value”)指定的位置。如果我满意默认名称,可以使用df %>% pivot_longer(c("a", "b"))

现在您可以像往常一样绘制图表,例如:

ggplot(df_wide, aes(x = time, y = val, color = colname)) + geom_line()

enter image description here


我建议在您的回答中添加require(tidyr)require(ggplot2),这样它就可以成为一个最小工作示例了。 - Alessandro Jacopson
@AlessandroJacopson 我认为我已经明确表明这些是必需的了。无论如何,如果代码与解释交织在一起,MWE是否有用? - qwr
对我来说很有用,不过这也是个人口味问题,感谢你的回答。 - Alessandro Jacopson
1
应该将其命名为 df_long,而不是 df_wide - Julien

5

使用 lattice

library(lattice)

df <- data.frame(time = 1:10,
                 a = cumsum(rnorm(10)),
                 b = cumsum(rnorm(10)),
                 c = cumsum(rnorm(10)))

form <- as.formula(paste(paste(names(df)[- 1],  collapse = ' + '),  
                         'time',  sep = '~'))

xyplot(form,  data = df,  type = 'b',  outer = TRUE)

3

您可以使用 main 选项指定标题(以及轴的标题通过 xlabylab)。例如:

plot(data[,i], main=names(data)[i])

如果您想绘制(并保存)数据框的每个变量,您应该使用 pngpdf 或者任何其他所需的图形驱动程序,并在此之后发出 dev.off() 命令。例如:

data <- read.csv("sample.csv",header=T,sep=",")
for (i in 1:length(data)) {
    pdf(paste('fileprefix_', names(data)[i], '.pdf', sep='')
    plot(data[,i], ylab=names(data[i]), type="l")
    dev.off()
}

或者使用par()函数的mfrow参数将所有图绘制到同一张图片上。例如:使用par(mfrow=c(2,2)将下面的4个图包含在同一张“图片”中。


3
我没有这台电脑上安装R,但是我可以试着给你提供一些帮助。你可以使用par在一个窗口中显示多个图形,或者像这样在显示下一页之前提示点击。
plotfun <- function(col) 
  plot(data[ , col], ylab = names(data[col]), type = "l")
par(ask = TRUE)
sapply(seq(1, length(data), 1), plotfun)

1
如果 .csv 文件中的列名不是有效的 R 名称:
data <- read.csv("sample.csv",sep=";",head=TRUE)
data2 <- read.csv("sample.csv",sep=";",head=FALSE,nrows=1)

for ( i in seq(1,length( data ),1) ) plot(data[,i],ylab=data2[1,i],type="l")

1
由于您只使用data2的第一行,因此在read.csv中设置nrows = 1会更有效率。 - Rustam Guliev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接