• 主页
  • 课程

    关于课程

    • 课程归档
    • 成为一名讲师
    • 讲师信息
    同等学历教学

    同等学历教学

    免费
    阅读更多
  • 特色
    • 展示
    • 关于我们
    • 问答
  • 事件
  • 个性化
  • 博客
  • 联系
  • 站点资源
    有任何问题吗?
    (00) 123 456 789
    weinfoadmin@weinformatics.cn
    注册登录
    恒诺新知
    • 主页
    • 课程

      关于课程

      • 课程归档
      • 成为一名讲师
      • 讲师信息
      同等学历教学

      同等学历教学

      免费
      阅读更多
    • 特色
      • 展示
      • 关于我们
      • 问答
    • 事件
    • 个性化
    • 博客
    • 联系
    • 站点资源

      未分类

      • 首页
      • 博客
      • 未分类
      • ComplexHeatmap 之 A Single Heatmap 续(二)

      ComplexHeatmap 之 A Single Heatmap 续(二)

      • 发布者 weinfoadmin
      • 分类 未分类, 老俊俊的生信笔记
      • 日期 2021年9月10日
      • 评论 0评论

      感谢老俊俊的大力支持。我们会每日跟新,欢迎您关注老俊俊的生信笔记。


      点击上方 关注我们


      这一节结束A Single Heatmap 篇,下一章介绍 热图的注释 。

      7、自定义热图主体

      热图主体可以自定义添加更多类型的图形。默认情况下,热图主体由具有不同填充颜色的小矩形矩阵(在本文档的其他部分可能称为网格,但在此处称为“单元格”)组成。但是,也可以在热图上添加更多图形或符号作为附加层。有两个参数 cell_fun 和 layer_fun ,它们都可以是用户自定义的函数。

      cell_fun:

      cell_fun 在每个单元格中重复绘制,内部在两个嵌套的 for 循环中执行,而 layer_fun 是 cell_fun 的矢量化版本。cell_fun 更容易理解,但 layer_fun 执行速度更快,更可定制。

      cell_fun 需要一个带有 7 个参数的函数(参数名称可以与以下不同,但顺序必须相同),它们是:

      • j: 矩阵中的 列 索引。列索引对应于视口中的 x 方向,这就是将 j 作为第一个参数的原因。
      • i: 矩阵 行 索引。
      • x: 在热图主体的视口中测量的单元格中点的 x 坐标。
      • y: 在热图主体的视口中测量的单元格中点的 y 坐标。
      • width: 单元格的宽度。该值是 unit(1/ncol(sub_mat), "npc") 其中 sub_mat 对应于通过行拆分和列拆分的子矩阵。
      • height: 单元格的高度。值为 unit(1/nrow(sub_mat), "npc")。
      • fill: 单元格的颜色。

      在每个单元格中执行时,七个参数的值会自动发送到函数里面。

      最常见的用途是将矩阵中的 值 添加到热图中:

      small_mat = mat[1:9, 1:9]
      col_fun = colorRamp2(c(-2, 0, 2), c("green", "white", "red"))
      Heatmap(small_mat, name = "mat", col = col_fun,
          cell_fun = function(j, i, x, y, width, height, fill) {
              grid.text(sprintf("%.1f", small_mat[i, j]), x, y, gp = gpar(fontsize = 10))
      })

      只添加正数:

      Heatmap(small_mat, name = "mat",  col = col_fun,
          cell_fun = function(j, i, x, y, width, height, fill) {
              if(small_mat[i, j] > 0)
                  grid.text(sprintf("%.1f", small_mat[i, j]), x, y, gp = gpar(fontsize = 10))
      })

      分割热图:

      Heatmap(small_mat, name = "mat", col = col_fun,
          row_km = 2, column_km = 2,
          cell_fun = function(j, i, x, y, width, height, fill) {
              grid.text(sprintf("%.1f", small_mat[i, j]), x, y, gp = gpar(fontsize = 10))
      })

      在下面的例子中,我们制作了一个热图,其中显示了与 corrplot 包相似的相关矩阵:

      cor_mat = cor(small_mat)
      od = hclust(dist(cor_mat))$order
      cor_mat = cor_mat[od, od]
      nm = rownames(cor_mat)
      col_fun = circlize::colorRamp2(c(-1, 0, 1), c("green", "white", "red"))
      # `col = col_fun` here is used to generate the legend
      Heatmap(cor_mat, name = "correlation", col = col_fun, rect_gp = gpar(type = "none"),
          cell_fun = function(j, i, x, y, width, height, fill) {
              grid.rect(x = x, y = y, width = width, height = height,
                  gp = gpar(col = "grey", fill = NA))
              if(i == j) {
                  grid.text(nm[i], x = x, y = y)
              } else if(i > j) {
                  grid.circle(x = x, y = y, r = abs(cor_mat[i, j])/2 * min(unit.c(width, height)),
                      gp = gpar(fill = col_fun(cor_mat[i, j]), col = NA))
              } else {
                  grid.text(sprintf("%.1f", cor_mat[i, j]), x, y, gp = gpar(fontsize = 10))
              }
          }, cluster_rows = FALSE, cluster_columns = FALSE,
          show_row_names = FALSE, show_column_names = FALSE)

      layer_fun:

      cell_fun 逐个单元添加图形,而 layer_fun 以块方式添加图形。与 cell_fun 类似,layer_fun 也需要七个参数,但都是向量形式(layer_fun 也可以有第八个和第九个参数,本节稍后介绍):

      # code only for demonstration
      Heatmap(..., layer_fun = function(j, i, x, y, w, h, fill) {...})
      # or you can capitalize the arguments to mark they are vectors,
      # the names of the argumetn do not matter
      Heatmap(..., layer_fun = function(J, I, X, Y, W, H, F) {...})

      j 和 i 仍然包含与原始矩阵对应的列和行索引,但由于现在 layer_fun 适用于一个单元格块(或热图块,如果热图被分割),j 和 i 是当前热图切片里所有单元格的向量。同理,x、y、w、h 和 fill 都是当前热图切片中所有单元格对应的向量。

      由于 j 和 i 现在是向量,为了获得矩阵中的相应值,我们不能使用 mat[j, i] 形式,因为它为你提供了一个具有 length(i) 行和 length(j) 列的子矩阵。相反,我们可以使用 ComplexHeatmap 中的 pindex() 函数,这类似于矩阵的成对索引,以下示例:

      mfoo = matrix(1:9, nr = 3)
      mfoo[1:2, c(1, 3)]
      ##      [,1] [,2]
      ## [1,]    1    7
      ## [2,]    2    8
      # but we actually want mfoo[1, 1] and mfoo[2, 3]
      pindex(mfoo, 1:2, c(1, 3))
      ## [1] 1 8

      下一个示例显示了在热图上添加文本的 layer_fun 版本。和 cell_fun 版本基本一致:

      col_fun = colorRamp2(c(-2, 0, 2), c("green", "white", "red"))
      Heatmap(small_mat, name = "mat", col = col_fun,
          layer_fun = function(j, i, x, y, width, height, fill) {
              # since grid.text can also be vectorized
              grid.text(sprintf("%.1f", pindex(small_mat, i, j)), x, y, gp = gpar(fontsize = 10))
      })

      添加正数:

      Heatmap(small_mat, name = "mat", col = col_fun,
          layer_fun = function(j, i, x, y, width, height, fill) {
              v = pindex(small_mat, i, j)
              l = v > 0
              grid.text(sprintf("%.1f", v[l]), x[l], y[l], gp = gpar(fontsize = 10))
      })

      当热图被分割时,layer_fun 应用于每个切片:

      Heatmap(small_mat, name = "mat", col = col_fun,
          row_km = 2, column_km = 2,
          layer_fun = function(j, i, x, y, width, height, fill) {
              v = pindex(small_mat, i, j)
              grid.text(sprintf("%.1f", v), x, y, gp = gpar(fontsize = 10))
              if(sum(v > 0)/length(v) > 0.75) {
                  grid.rect(gp = gpar(lwd = 2, fill = "transparent"))
              }
      })

      layer_fun 还可以有另外两个参数,它们是当前行切片和列切片的索引。例如 我们想为右上角和左下角的切片添加边框:

      Heatmap(small_mat, name = "mat", col = col_fun,
          row_km = 2, column_km = 2,
          layer_fun = function(j, i, x, y, width, height, fill, slice_r, slice_c) {
              v = pindex(small_mat, i, j)
              grid.text(sprintf("%.1f", v), x, y, gp = gpar(fontsize = 10))
              if(slice_r != slice_c) {
                  grid.rect(gp = gpar(lwd = 2, fill = "transparent"))
              }
      })

      layer_fun 的优势在于不仅可以 快速添加图形 ,而且还提供了更多 自定义热图的可能性。考虑以下可视化:对于热图中的每一行,如果相邻两列中的值具有相同的符号,我们根据两个值的符号添加一条红线或一条绿线。由于现在单元格中的图形依赖于其他单元格,因此只能通过 layer_fun 来实现它:

      Heatmap(small_mat, name = "mat", col = col_fun,
          row_km = 2, column_km = 2,
          layer_fun = function(j, i, x, y, w, h, fill) {
              # restore_matrix() is explained after this chunk of code
              ind_mat = restore_matrix(j, i, x, y)
              for(ir in seq_len(nrow(ind_mat))) {
                  # start from the second column
                  for(ic in seq_len(ncol(ind_mat))[-1]) {
                      ind1 = ind_mat[ir, ic-1] # previous column
                      ind2 = ind_mat[ir, ic]   # current column
                      v1 = small_mat[i[ind1], j[ind1]]
                      v2 = small_mat[i[ind2], j[ind2]]
                      if(v1 * v2 > 0) { # if they have the same sign
                          col = ifelse(v1 > 0, "darkred", "darkgreen")
                          grid.segments(x[ind1], y[ind1], x[ind2], y[ind2],
                              gp = gpar(col = col, lwd = 2))
                          grid.points(x[c(ind1, ind2)], y[c(ind1, ind2)],
                              pch = 16, gp = gpar(col = col), size = unit(4, "mm"))
                      }
                  }
              }
          }
      )

      发送到 layer_fun 的值都是向量(用于网格图形函数的向量化),但是,layer_fun 应用到的热图切片仍然由矩阵表示,因此,如果所有参数都非常方便 在 layer_fun 中可以转换为当前切片的子矩阵。在这里,如上例所示,restore_matrix() 完成了这项工作。restore_matrix() 直接接受 layer_fun 中的前四个参数,返回一个 索引矩阵 ,其中的行和列对应当前切片中的行和列,从上到下,从左到右。矩阵中的值是例如的自然顺序 当前切片中的向量 j。

      Heatmap(small_mat, name = "mat", col = col_fun,
          row_km = 2, column_km = 2,
          layer_fun = function(j, i, x, y, w, h, fill) {
              ind_mat = restore_matrix(j, i, x, y)
              print(ind_mat)
          }
      )

      左上角切片的第一个输出:

           [,1] [,2] [,3] [,4] [,5]
      [1,]    1    4    7   10   13
      [2,]    2    5    8   11   14
      [3,]    3    6    9   12   15

      这是一个三行五列的索引矩阵,其中第一行对应于切片中的顶行。矩阵中的值对应于 layer_fun 中 j、i、x、y、… 中的自然索引(即 1、2、…)。现在,如果我们想在左上角切片的第二列上添加值,放置在 layer_fun 中的代码将如下所示:

      for(ind in ind_mat[, 2]) {
          grid.text(small_mat[i[ind], j[ind]], x[ind], y[ind], ...)
      }

      现在更容易理解第二个例子:我们想在每个切片的第二行和第三列添加点:

      Heatmap(small_mat, name = "mat", col = col_fun,
          row_km = 2, column_km = 2,
          layer_fun = function(j, i, x, y, w, h, fill) {
              ind_mat = restore_matrix(j, i, x, y)
              ind = unique(c(ind_mat[2, ], ind_mat[, 3]))
              grid.points(x[ind], y[ind], pch = 16, size = unit(4, "mm"))
          }
      )

      8、热图尺寸

      width、heatmap_width、height 和 heatmap_height 控制热图的大小。默认情况下,所有热图组件都有固定的宽度或高度,例如行树状图的宽度为 1cm。热图主体的宽度或高度填充最终绘图区域的其余区域,这意味着,如果在交互式图形窗口中绘制它并通过拖动它来更改窗口的大小,则热图主体的大小为自动调整。

      heatmap_width 和 heatmap_height 控制包括所有热图组件(不包括图例)在内的完整热图的宽度/高度,而 width 和 height 仅控制 heamtap 主体的宽度/高度。所有这四个参数都可以设置为绝对单位:

      Heatmap(mat, name = "mat", width = unit(8, "cm"), height = unit(8, "cm"))
      Heatmap(mat, name = "mat", heatmap_width = unit(8, "cm"), heatmap_height = unit(8, "cm"))

      当热图的大小设置为绝对单位时,图的大小可能大于热图的大小,这会在热图周围产生空白区域。热图的大小可以通过 ComplexHeatmap::width() 和 ComplexHeatmap::height() 函数获取:

      ht = Heatmap(mat, name = "mat", width = unit(8, "cm"), height = unit(8, "cm"))
      ht = draw(ht) # you must call draw() to reassign the heatmap variable
      ComplexHeatmap:::width(ht)
      ## [1] 118.851591171994mm
      ComplexHeatmap:::height(ht)
      ## [1] 114.717557838661mm

      ht = Heatmap(mat, name = "mat", heatmap_width = unit(8, "cm"),
          heatmap_height = unit(8, "cm"))
      ht = draw(ht)
      ComplexHeatmap:::width(ht)
      ## [1] 94.8877245053272mm
      ComplexHeatmap:::height(ht)
      ## [1] 83.8660578386606mm

      9、绘图

      Heatmap() 函数实际上只是一个构造函数,也就是说它只是将所有的数据和配置放入 Heatmap 类中的对象中。只有在调用 draw() 方法时才会执行聚类。在交互模式下(例如,交互式 R 终端,可以在其中逐行键入 R 代码),直接调用 Heatmap() 而不返回任何对象会打印对象和热图的打印方法(或 S4 show() 方法) 类对象在内部调用 draw()。因此,如果在 R 终端中键入 Heatmap(…),它看起来像是 plot() 之类的绘图函数,需要注意它实际上不是真的,并且在以下情况下,可能看不到任何绘图:

      • 你把 Heatmap(…) 放在一个函数里,
      • 你把 Heatmap(…) 放在像 for 或 if-else 这样的代码块中
      • 你把 Heatmap(…) 放在一个 Rscript 中,然后在命令行下运行它。

      原因是在以上三种情况下,show() 方法不会被调用,因此 draw() 方法也不会被执行。因此,要绘制绘图,需要显式调用 draw():draw(Heatmap(...)):

      # code only for demonstration
      ht = Heatmap(...)
      draw(ht)

      draw() 函数实际上应用于 HeatmapList 类中的热图列表。单个 Heatmap 类的 draw() 方法构造一个只有一个 heatmap 的 HeatmapList 并调用 HeatmapList 类的 draw() 方法。draw() 函数接受更多参数,例如 控制图例:

      draw(ht, heatmap_legend_side, padding, ...)

      10、提取顺序

      热图的 行/列顺序 可以通过 row_order()/column_order() 函数获得。可以直接应用于 Heatmap() 返回的热图对象或 draw() 返回的对象。下面我们以 row_order() 为例:

      small_mat = mat[1:9, 1:9]
      ht1 = Heatmap(small_mat)
      row_order(ht1)
      ## [1] 5 7 2 4 9 6 8 1 3

      ht2 = draw(ht1)
      row_order(ht2)
      ## [1] 5 7 2 4 9 6 8 1 3

      如上一节所述,Heatmap() 函数 不执行聚类,因此,当直接在 ht1 上应用 row_order() 时,将首先执行聚类。稍后在通过 draw(ht1) 制作热图时,将再次应用聚类。如果在热图中设置 k-means 聚类,这可能是一个问题。由于聚类应用了两次,k-means 可能会给你不同的聚类,这意味着你可能从 row_order() 得到不同的结果,你可能有不同的热图。

      在下面的代码块中,o1、o2 和 o3 可能不同,因为每次都执行 k 均值聚类:

      # code only for demonstration
      ht1 = Heatmap(small_mat, row_km = 2)
      o1 = row_order(ht1)
      o2 = row_order(ht1)
      ht2 = draw(ht1)
      o3 = row_order(ht2)
      o4 = row_order(ht2)

      draw() 函数返回已经重新排序的热图(或者更准确地说,热图列表),并且应用 row_order() 只是从对象中提取行顺序,这确保行顺序与所示的行顺序完全相同热图。在上面的代码中,o3 始终与 o4 相同。

      因此,获取行/列顺序的优选方法如下:

      # code only for demonstration
      ht = Heatmap(small_mat)
      ht = draw(ht)
      row_order(ht)
      column_order(ht)

      如果行/列被拆分,行顺序或列顺序将是一个列表:

      ht = Heatmap(small_mat, row_km = 2, column_km = 3)
      ht = draw(ht)
      row_order(ht)

      ## $`2`
      ## [1] 5 7 2 4
      ##
      ## $`1`
      ## [1] 9 6 8 1 3

      column_order(ht)

      ## $`1`
      ## [1] 6 2 7
      ##
      ## $`3`
      ## [1] 1 3 4 5
      ##
      ## $`2`
      ## [1] 8 9

      同样,row_dend()/column_dend() 函数返回树状图。它返回单个树状图或树状图列表,具体取决于热图是否被分割:

      ht = Heatmap(small_mat, row_km = 2)
      ht = draw(ht)
      row_dend(ht)

      ## $`2`
      ## 'dendrogram' with 2 branches and 4 members total, at height 2.946428
      ##
      ## $`1`
      ## 'dendrogram' with 2 branches and 5 members total, at height 2.681351

      column_dend(ht)

      ## 'dendrogram' with 2 branches and 9 members total, at height 4.574114

      11、提取子集热图

      由于热图是矩阵的表示,因此也有热图类的子集方法:

      ht = Heatmap(mat, name = "mat")
      dim(ht)
      ## [1] 18 24

      ht[1:10, 1:10]

      注释子集也可被提取:

      ht = Heatmap(mat, name = "mat", row_km = 2, column_km = 3,
          col = colorRamp2(c(-2, 0, 2), c("green", "white", "red")),
          top_annotation = HeatmapAnnotation(foo1 = 1:24, bar1 = anno_points(runif(24))),
          right_annotation = rowAnnotation(foo2 = 18:1, bar2 = anno_barplot(runif(18)))
      )
      ht[1:9*2 - 1, 1:12*2] # odd rows, even columns

      如果热图组件类似于向量,则它们也被 子集化 。热图中的某些配置在子集化时保持不变,例如:如果在原始热图中设置了 row_km,则保留 k-means 的配置并在子热图中执行。所以在下面的例子中,k-means 聚类只在为 ht2 制作热图时执行:

      ht = Heatmap(mat, name = "mat", row_km = 2)
      ht2 = ht[1:10, 1:10]
      ht2


      收官!


      代码 我上传到 QQ 群 老俊俊生信交流群 文件夹里。欢迎加入。加我微信我也拉你进 微信群聊 老俊俊生信交流群 哦。

      群二维码:


      老俊俊微信:




      知识星球:



      所以今天你学习了吗?

      欢迎小伙伴留言评论!

      点击我留言!

      今天的分享就到这里了,敬请期待下一篇!

      最后欢迎大家分享转发,您的点赞是对我的鼓励和肯定!

      如果觉得对您帮助很大,赏杯快乐水喝喝吧!

      推 荐 阅 读




      • circlize 之可视化基因组数据

      • circlize 之 Advanced layout

      • circlize 之 circos.heatmap()

      • circlize 之 Implement high-level circular plots

      • 怎么批量合并 data.frame ?

      • QPCRpro 正式上线!

      • circlize 之 Legends

      • QPCR数据添加 p 值和显著性一次解决!

      • circlize 之 Graphics

      • circlize 之 Introduction

      • circlize 之 Circular layout

      • 鉴定差异翻译效率基因之 deltaTE 下篇

      • 鉴定差异翻译效率基因之 deltaTE 上篇

      • 鉴定差异翻译效率基因之 Riborex

      • purrr 包之 list 处理系列函数

      • purrr 包之 map 系列函数

      • 批量绘制单基因相关性图

      • Y 叔出品:ggfun

      • 神器之 computeMatrix + 绘图

      • Deeptools 神器之 bamCoverage

      • 在线版shiny pheatmap!

      • QPCR数据快速分析和绘图 — by shiny

      • RNA-seq:Salmon 快速定量

      • RNA-seq:Salmon 定量结果差异分析

      • 用R提取代表转录本

      • 画个CNS级别火山图!

      • R Tips :split 函数

      • 什么? R 版 Hisat2

      • R Tips :match 函数

      • conda 安装软件报错

      • MetaProfile on Transcript

      • 提取代表转录本之 gencode

      • 附近含有 m6A 修饰的 Stop Codon 序列提取

      • Introduction of m6A

      • RNA-seq : Hisat2+Stringtie+DESeq2

      • shiny VennDiagram

      • shiny CountToTPM/FPKM

      • 自己模仿画个– m6A distribution on transcript

      • 怎么把 shiny App 做成 exe 文件进行分发

      • shiny-server内网穿透

      • 在线版shiny pheatmap!

      • 用shiny创作在线火山图绘制App

      • circlize 之 Create plotting regions

      • circlize 之 High-level genomic functions

      • R 爬虫之爬取文献信息

      • R 爬虫之爬取公众号图片

      • 跟着 cell 绘制条形堆叠图和分面小提琴图

      • R 爬虫之爬取 NCBI 文献

      • ggplot 分面绘图一网打尽

      • circlize 之 chordDiagram 函数

      • circlize 之 chordDiagram 函数高级用法

      • R 绘制柱形偏差图

      • R 爬虫之爬取文献影响因子

      • R爬虫之 html 简介

      • R 爬虫之爬取 CRAN 官网 R 包信息

      • ZhouLab 星球

      • R爬虫之 html 简介(续)

      • 绘制带连线的柱状堆积图

      • 连线柱状堆积图进阶

      • circlize 绘图小问题解答

      • 批量读取文件一文搞定

      • 保姆级:手把手教你绘制环形基因表达热图

      • 环形热图进阶

      • 奇怪的图例作业

      • 基础绘图 grid 包,你值得学习!

      • igraph 牛刀小试

      • ggraph 绘制基因关系网络图

      • 新的 m6A 识别蛋白 MOV10

      • 听说你还不会 plot 函数?

      • 你的 legend 还是画的很丑?

      • 你有一份作业未领取

      • 你要的 ComplexHeatmap TA 来了!

      • ComplexHeatmap 之 A Single Heatmap 续(一)

      请关注“恒诺新知”微信公众号,感谢“R语言“,”数据那些事儿“,”老俊俊的生信笔记“,”冷🈚️思“,“珞珈R”,“生信星球”的支持!

      • 分享:
      作者头像
      weinfoadmin

      上一篇文章

      ComplexHeatmap 之 Heatmap Annotations
      2021年9月10日

      下一篇文章

      ComplexHeatmap 之 A Single Heatmap 续(一)
      2021年9月10日

      你可能也喜欢

      2-1675088548
      lncRNA和miRNA生信分析系列讲座免费视频课和课件资源包,干货满满
      30 1月, 2023
      9-1675131201
      如何快速批量修改 Git 提交记录中的用户信息
      26 1月, 2023
      8-1678501786
      肿瘤细胞通过改变CD8+ T细胞中的丙酮酸利用和琥珀酸信号来调控抗肿瘤免疫应答。
      7 12月, 2022

      留言 取消回复

      要发表评论,您必须先登录。

      搜索

      分类

      • R语言
      • TCGA数据挖掘
      • 单细胞RNA-seq测序
      • 在线会议直播预告与回放
      • 数据分析那些事儿分类
      • 未分类
      • 生信星球
      • 老俊俊的生信笔记

      投稿培训

      免费

      alphafold2培训

      免费

      群晖配置培训

      免费

      最新博文

      Nature | 单细胞技术揭示衰老细胞与肌肉再生
      301月2023
      lncRNA和miRNA生信分析系列讲座免费视频课和课件资源包,干货满满
      301月2023
      如何快速批量修改 Git 提交记录中的用户信息
      261月2023
      logo-eduma-the-best-lms-wordpress-theme

      (00) 123 456 789

      weinfoadmin@weinformatics.cn

      恒诺新知

      • 关于我们
      • 博客
      • 联系
      • 成为一名讲师

      链接

      • 课程
      • 事件
      • 展示
      • 问答

      支持

      • 文档
      • 论坛
      • 语言包
      • 发行状态

      推荐

      • iHub汉语代码托管
      • iLAB耗材管理
      • WooCommerce
      • 丁香园论坛

      weinformatics 即 恒诺新知。ICP备案号:粤ICP备19129767号

      • 关于我们
      • 博客
      • 联系
      • 成为一名讲师

      要成为一名讲师吗?

      加入数以千计的演讲者获得100%课时费!

      现在开始

      用你的站点账户登录

      忘记密码?

      还不是会员? 现在注册

      注册新帐户

      已经拥有注册账户? 现在登录

      close
      会员购买 你还没有登录,请先登录
      • ¥99 VIP-1个月
      • ¥199 VIP-半年
      • ¥299 VIP-1年
      在线支付 激活码

      立即支付
      支付宝
      微信支付
      请使用 支付宝 或 微信 扫码支付
      登录
      注册|忘记密码?