• R语言
  • 请问如何用ggplot画出曲线簇?

函数xy=z,z分别取值1、2、3、4,x和y的取值区间为(0,10],如何实现用ggplot画出这4条曲线?
谢谢。

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

        dapengde 哈哈,原来是 expand.grid(),我印象里有个函数可以产生这个效果,但是刚才没有想起来是哪个。

          Liechi 我也很少用。刚才试了一下,可以在 expand.grid() 里指定列名称,所以去掉了一行。

            谢谢各位。短路忘记color分类了。

            dapengde 顺便再精简一下,去掉 dplyr 的依赖

            library(ggplot2)
            library(magrittr)
            expand.grid(x =seq(0.1, 10, by = 0.1), z = 1:4) %>% 
              transform(y = z/x, z = as.factor(z)) %>% 
              ggplot() +
              geom_line(aes(x, y, color = z))

            PS 我刚精简完,发现 dapengde 修改了自己的回帖, 😅 然后默默地删,最后还是回一下

              再来个 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 确实优雅。

                dapengde 来,老夫聊发个少年狂:论 R 基础图形,当今世上恐怕没几个人是我的对手,毕竟我是写过《古代统计图形》的,哈哈哈。两行代码给你搞定:

                for (z in 4:1) curve(z/x, 0, 10, add = z < 4, col = z)
                legend('topright', legend = 4:1, col = 4:1, lty = 1, title = 'z')

                  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()根本用不上。

                    yihui 看完你的解法,耳边响起了熟悉的旋律:

                    问世间 是否此山最高
                    或者另有高处比天高
                    ...

                    dapengde 我已用歌声表达了我的感受。

                    我现在也有点极乐净土病了:最开始版本的代码,顺手祭出了神包 玛格丽特,写完后惊觉整个代码段,其实只有一处用了 %>%df %>% ggplot() + ...),赶紧灰溜溜地把 玛格丽特 请回去,改写成 ggplot(df, ...) + ...

                      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")

                        Liechi
                        df %>% ggplot的一个好处是ggplot里aes的列名自动补齐终于可以正常工作了…发现这一点之后我就再也回不到从前啦

                          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 擂台赛。

                              dapengde 赞呐!

                              yihui 缩略的好,这次放出的《“古”代统计图形》是我看到最完整的,既然11年就有365页了,为啥当时不出版?现在看的话,部分内容需要更新了

                                tctcab 果然如此。这个差异以前没有意识到,看来是回不去了。