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


76

数据框有n列,我想得到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
加文·辛普森

3
read.csv可以简化为,read.csv("sample.csv")因为其他参数仅被设置为其默认值。
G. Grothendieck'2

Answers:


85

ggplot2软件包需要一些学习,但是结果看起来非常不错,您得到了漂亮的图例以及许多其他不错的功能,而无需编写太多代码。

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 ~ .)

在此处输入图片说明 在此处输入图片说明


好的答案,但是为什么您实际上需要重塑?
eliasah '16

谢谢@VerenaHaunschmid我后来想通了:-)
eliasah

43

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

plot.ts(data)

哪个产生(其中X1-X4是列名):

在此处输入图片说明

查看所有选项的?plot.ts。

如果您不想进一步控制绘图功能并且不使用循环,则还可以执行以下操作:

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

谢谢,即使它与时间序列有关,我认为它也可以帮助我掌握数据。我喜欢单线!
亚历山德罗·贾科普森

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,还应该添加:col=rainbow(ncol(my.data))或类似的东西,以保持线条的可读性。
亮星

13

您可以赴汤蹈火,你的解决方案转换为一个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)

这使: 动物园标绘功能示例


11

我很惊讶没有人提及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,它从哪里来?
亚历山德罗·贾科普森

1
@AlessandroJacopson这是我通常使用的调色板功能。它是从hyperSpec包装中取出的。但是最好在这里使用更多已知的功能,因此我将其更改为rainbow。如果您不了解调色板功能,请参阅?rainbow。抱歉造成混淆。
Rustam Guliev

7

使用上面的一些技巧(特别感谢@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])}
  }
}

祝你好运,马特。


4

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

您可以使用选项指定标题(以及通过xlab和指定轴的标题ylabmain。例如:

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()
}

或使用的mfrow参数将所有图绘制到同一图像par()。例如:用于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)

2

不幸的是,ggplot2不能(不轻松)地将数据转换为长格式而没有这种方法。您可以尝试解决它,但是进行数据转换会更容易。这里的所有方法,包括meltreshape2,gathertidyr和pivot_longertidyr:将data.frame从宽格式重塑为长格式

这是一个使用的简单示例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”)指定的任何内容。如果可以使用默认名称,则可以使用use df %>% pivot_longer(c("a", "b"))

现在您可以正常绘制,例如。

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

在此处输入图片说明


我会在您的回答中加上require(tidyr)require(ggplot2),这样它将成为“最小工作示例”。
亚历山德罗·贾科普森

@AlessandroJacopson我以为我很清楚那些是必需的。无论如何,如果代码中插有解释,MWE是否有用?
qwr

对我来说,它很有用,无论如何这都取决于口味,谢谢您的回答。
亚历山德罗·贾科普森

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
既然你从数据2只使用第一行,这将是更有效地设置nrows = 1read.csv
Rustam Guliev

0

对于相同的问题,此链接对我有很大帮助:

p = ggplot() + 
  geom_line(data = df_plot, aes(x = idx, y = col1), color = "blue") +
  geom_line(data = df_plot, aes(x = idx, y = col2), color = "red") 

print(p)

https://rpubs.com/euclid/343644

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.