函数xy=z,z分别取值1、2、3、4,x和y的取值区间为(0,10],如何实现用ggplot画出这4条曲线?
谢谢。
请问如何用ggplot画出曲线簇?
- 已编辑
medo 一个不漂亮的画法:
library(ggplot2)
x <- seq(0.1, 10, by = 0.1)
z <- c(1, 2, 3, 4)
y1 <- z[1]/x
y2 <- z[2]/x
y3 <- z[3]/x
y4 <- z[4]/x
z <- rep(c("z1", "z2", "z3", "z4"), each = 100)
x <- rep(x, 4)
y <- c(y1, y2, y3, y4)
df <- data.frame(z, x, y)
ggplot(df, aes(x = x, y = y, color = z)) + geom_line() +
coord_cartesian(ylim = c(0, 10), expand = F)
要是其他成员有比较好的方法,希望能学习一下。
受大鹏启发,精简一下:
library(ggplot2)
x <- seq(0.1, 10, by = 0.1)
z <- rep(1:4, each = 100)
df <- data.frame(x, y = z/x, z = factor(z))
ggplot(df, aes(x = x, y = y, color = z)) + geom_line() +
coord_cartesian(ylim = c(0, 10), expand = F)
给自己的笔记:产生数据组合,可以用 expand.grid()
。
- 已编辑
Liechi 在你基础上改了一下:
library(ggplot2)
library(magrittr)
expand.grid(x =seq(0.1, 10, by = 0.1), z = 1:4) %>%
transform(y = z/x, z = factor(z)) %>%
ggplot() +
geom_line(aes(x, y, color = z))
无管道版:
library(ggplot2)
ggplot(
transform(
expand.grid(
x = seq(0.1, 10, by = 0.1),
z = 1:4),
y = z / x,
z = factor(z))) +
geom_line(aes(x, y, color = z))
谢谢各位。短路忘记color分类了。
- 已编辑
再来个 Base R 版,去掉所有额外包的依赖,打擂:
df <- transform(
expand.grid(
x = seq(0.1, 10, by = 0.1),
z = 1:4),
y = z / x)
plot(df$x[df$z == i], df$y[df$z == i], type = 'l', xlab = 'x', ylab = 'y')
for(i in 2:4) lines(df$x[df$z == i], df$y[df$z == i], col = i)
legend('topright', legend = 1:4, col = 1:4, lty = 1, title = 'z')
以及 lattice 版:
lattice::xyplot(y~x, groups = z, data = df, type = 'l', ylim = c(0, 10), auto.key = list(corner = c(1, 1), points = FALSE, lines = TRUE))
相比之下,ggplot2 确实优雅。
- 已编辑
yihui 看到这里方才惊觉,我被 tidyverse 暗中洗脑了。上面我的 Base R 方案完全没必要先生成 data.frame。下面这样就足够了:
x = seq(0.1, 10, by = 0.1)
plot(x, 1/x, type = 'l', xlab = 'x', ylab = 'y')
for (z in 2:4) lines(x, z/x, col = z)
legend('topright', legend = 1:4, col = 1:4, lty = 1, title = 'z')
curve()
我好像从没用过。
@Liechi 瞧, expand.grid()
根本用不上。
- 已编辑
matplot(outer(seq(0.1, 10, by = 0.1), 1:4, function(x, a) a / x),
xlab = "x", ylab = "z/x", type = "l", col = 1:4, lty = 1
)
legend("topright", legend = 4:1, col = 4:1, lty = 1, title = "z")
Cloud2016 我来打个代码高尔夫,把你的代码略微缩一下(代价是不那么易懂了):
matplot(t(outer(1:4, (1:100)/10, `/`)),
xlab = "x", ylab = "z/x", type = "l", col = 1:4, lty = 1
)
不过还是不如我的 curve()
方案短小,主要是 curve()
自动生成了横纵坐标的标题。
画数据图的话,ggplot 完胜;画示意图的话,R 基础图形还是有点优势的。前者本来就是建设在数据框基础上的,所以要画示意图还得事先生造出一个干净的数据框,在那之后一切都简单多了;后者则是纸笔模型,自己拿着笔画点画线,所以用来画数据图形则会显得很繁琐。
- 已编辑
涨见识了。我感觉我的极限就是 plot + lines,更高级的消化不了,隔断时间不用就忘干净。
建议以后对 cosx 所有的提问都给出 Base R 版和 Tidyverse 版 。做做大脑体操。简称 B 版和 T 版。我自告奋勇整理成书。书名我都想好了:BT 擂台赛。