cellassign:用于腫瘤微環(huán)境分析的單細(xì)胞注釋工具(9月Nature)

作者:苑曉梅
責(zé)編:SXY

單細(xì)胞測(cè)序?qū)υS多復(fù)雜組織重新進(jìn)行分解分析,打破了我們對(duì)細(xì)胞類型的固有認(rèn)知。通常情況下,研究人員首先通過(guò)無(wú)監(jiān)督聚類,獲得細(xì)胞簇,然后根據(jù)Marker基因手動(dòng)注釋每個(gè)簇可能的細(xì)胞類型,或者應(yīng)用"label transfer"比對(duì)到已經(jīng)分型的數(shù)據(jù)確定自己研究的細(xì)胞類型 (這也是單細(xì)胞整合分析的一個(gè)關(guān)鍵點(diǎn),具體關(guān)注我們的單細(xì)胞課程)。然而,對(duì)大型數(shù)據(jù)集根據(jù)Marker基因手動(dòng)注釋一來(lái)比較繁瑣,難以擴(kuò)展,二來(lái)Marker基因具有不唯一性,人為確定有選擇困難癥 (單細(xì)胞分群后,怎么找到Marker基因定義每一類群?)。"Label transfer"的方法需要預(yù)先注釋的數(shù)據(jù),容易受batch effects影響。

那么,就要敲黑板啦!

image

作者提出了cellassign(https://irrationone.github.io/cellassign/introduction-to-cellassign.html)-應(yīng)用概率模型綜合分析已知的細(xì)胞類型標(biāo)記基因,將單細(xì)胞RNA測(cè)序數(shù)據(jù)注釋為predefined or de novo cell types。該方法于2019年9月發(fā)表在Nature methods,原文是Probabilistic cell-type assignment of single-cell RNA-seq for tumor microenvironment profiling

流程概覽

cellassign基于Marker基因信息將單細(xì)胞RNA測(cè)序獲得的細(xì)胞分型匹配到已知細(xì)胞類型。與其他從單細(xì)胞RNA-seq數(shù)據(jù)中確定細(xì)胞類型的方法不同,cellassign不需要已經(jīng)標(biāo)記的單細(xì)胞或bulk數(shù)據(jù) - 只需要知道每個(gè)給定的基因是否是某種細(xì)胞類型的marker就好,想獲得這些Marker基因,可以看下CellMarker數(shù)據(jù)庫(kù)等。

以下為workflow (用戶的輸入是子圖a的上半部分:標(biāo)準(zhǔn)化后的表達(dá)矩陣和Marker基因-細(xì)胞類型對(duì)照表,輸出是細(xì)胞歸屬的已知細(xì)胞類型或新細(xì)胞類型):

image

包安裝

cellassign的安裝需要依賴于 tensorflow (機(jī)器學(xué)習(xí)經(jīng)典包,莫煩Python機(jī)器學(xué)習(xí)),可以根據(jù)以下步驟進(jìn)行安裝:

install.packages("tensorflow")library(tensorflow)install_tensorflow()

安裝cellassign

BiocManager::install('cellassign')

或者安裝開(kāi)發(fā)版

devtools::install_github("Irrationone/cellassign")

具體使用

library(SingleCellExperiment)
library(cellassign)

首先需要構(gòu)建SingleCellExperiment對(duì)象,當(dāng)然我們做到這步一般是已經(jīng)成功構(gòu)建過(guò)了,如果沒(méi)有構(gòu)建,可以參考以下代碼:

讀入數(shù)據(jù) (Smartseq2),讀入逗號(hào)或Tab鍵分隔的表達(dá)矩陣 (原始counts),存儲(chǔ)為數(shù)據(jù)框,行是基因,列是細(xì)胞。

#讀入逗號(hào)分隔的count matrix,存儲(chǔ)為數(shù)據(jù)框,該數(shù)據(jù)是單細(xì)胞大名鼎鼎的小鼠全器官數(shù)據(jù)集中的一部分
dat = read.delim("FACS/Kidney-counts.csv", sep=",", header=TRUE)dat[1:5,1:5]
##               X A14.MAA000545.3_8_M.1.1 E1.MAA000545.3_8_M.1.1
## 1 0610005C13Rik                       0                      0
## 2 0610007C21Rik                       1                      0
## 3 0610007L01Rik                       0                      0
## 4 0610007N19Rik                       0                      0
## 5 0610007P08Rik                       0                      0
##   M4.MAA000545.3_8_M.1.1 O21.MAA000545.3_8_M.1.1
## 1                      0                       0
## 2                      0                       0
## 3                      0                       0
## 4                      0                       0
## 5                      0                       0

數(shù)據(jù)庫(kù)第一列是基因名字,把它移除作為列名字:

dim(dat)
rownames(dat) <- dat[,1]
dat <- dat[,-1]

構(gòu)建scater對(duì)象 (更多操作見(jiàn) Hemberg-lab單細(xì)胞轉(zhuǎn)錄組數(shù)據(jù)分析(七)-導(dǎo)入10X和SmartSeq2數(shù)據(jù)Tabula Muris

sceset <- SingleCellExperiment(assays = list(counts = as.matrix(dat)), colData=cell_anns)

# 如果做實(shí)驗(yàn)室記錄了細(xì)胞來(lái)源的小鼠、處理等信息,可以整理成表格,采用read.table讀入存儲(chǔ)到call_anns里面一起構(gòu)建scater對(duì)象`
# sceset <- SingleCellExperiment(assays = list(counts = as.matrix(dat)), colData=cell_anns)
# 查看對(duì)象
str(sceset)

作者使用一個(gè)由10個(gè)標(biāo)記基因和500個(gè)細(xì)胞組成的SingleCellExperiment作為示例 (如果自己還沒(méi)有數(shù)據(jù),可以繼續(xù)用作者提供的數(shù)據(jù)操作):

data(example_sce)
print(example_sce)
#> class: SingleCellExperiment
#> dim: 10 500
#> metadata(1): params
#> assays(6): BatchCellMeans BaseCellMeans ... TrueCounts counts
#> rownames(10): Gene186 Gene205 ... Gene949 Gene994
#> rowData names(6): Gene BaseGeneMean ... DEFacGroup1 DEFacGroup2
#> colnames(500): Cell1 Cell2 ... Cell499 Cell500
#> colData names(5): Cell Batch Group ExpLibSize EM_group
#> reducedDimNames(0):
#> spikeNames(0):

為了方便起見(jiàn),在SingleCellExperiment的Group slot中注釋了真正的細(xì)胞類型 (這里是模擬的名字,Group1,2,3等):

print(head(example_sce$Group))
#> [1] "Group1" "Group2" "Group2" "Group1" "Group1" "Group1"

關(guān)于標(biāo)記基因分組,還提供了一個(gè)細(xì)胞類型與基因的二元矩陣示例(example_rho),如果基因是給定細(xì)胞類型的marker,則標(biāo)記為1,否則為0:我們先從各種文獻(xiàn)、數(shù)據(jù)庫(kù)(比如CellMarker)或者直接從PanglaoDB得到先驗(yàn)信息,如

image

將它以列表的形式讀入

example_rho<- list(B_cell = c("Gene186", "Gene269", "Gene526", "Gene536", "Gene994"),
                   T_cell = c("Gene205", "Gene575", "Gene754", "Gene773", "Gene949"))
print(str(example_rho))
#> List of 2
#>  $ B_cell: chr [1:5] "Gene186" "Gene269" "Gene526" "Gene536" ...
#>  $ T_cell: chr [1:5] "Gene205" "Gene575" "Gene754" "Gene773" ...
#> NULL

然后用函數(shù)marker_list_to_mat將其轉(zhuǎn)換為二進(jìn)制標(biāo)記基因矩陣。

example_rho <- marker_list_to_mat(example_rho)
print(example_rho)

#>         B_cell T_cell other
#> Gene186      1      0     0
#> Gene205      0      1     0
#> Gene269      1      0     0
#> Gene526      1      0     0
#> Gene536      1      0     0
#> Gene575      0      1     0
#> Gene754      0      1     0
#> Gene773      0      1     0
#> Gene949      0      1     0
#> Gene994      1      0     0

其中other表示非其中任一類型的細(xì)胞,也可用include_other=FALSE去掉該列。

表達(dá)矩陣標(biāo)準(zhǔn)化

cellassign識(shí)別的是scater對(duì)象example_sceslots部分內(nèi)容,需要用戶提供量化因子用于表達(dá)矩陣的標(biāo)準(zhǔn)化。

example_sce已經(jīng)預(yù)先做過(guò)運(yùn)算,操作自己的數(shù)據(jù)時(shí)建議使用scran包的computeSumFactors計(jì)算,代碼如下。(什么?你做的差異基因方法不合適?中提供了其它的計(jì)算方法和計(jì)算原理)

同時(shí)由于用于cell assign分析的scater對(duì)象只是原始表達(dá)矩陣的一部分,標(biāo)準(zhǔn)化時(shí)建議用原始表達(dá)矩陣所有基因進(jìn)行標(biāo)準(zhǔn)化。

qclust <- quickCluster(sceset, min.size = 30)
sceset <- computeSumFactors(sceset, sizes = 15, clusters = qclust)
sceset <- normalize(sceset)

Scater對(duì)象篩選

cellassign函數(shù)需要的scater對(duì)象是單細(xì)胞實(shí)驗(yàn)或輸入的基因表達(dá)矩陣的子集,只包含example_rho中含有的Marker gene的行;如果應(yīng)用自己的數(shù)據(jù),需要一步過(guò)濾 (example_sce測(cè)試數(shù)據(jù)已經(jīng)過(guò)濾過(guò),故跳過(guò)),代碼如下(注意:Marker gene中基因的命名規(guī)則與sceset中基因命名規(guī)則一致,比如都為ENSEMBL ID或都為Gene Symbol):

# 對(duì)scater對(duì)象進(jìn)行篩選
sceset <- sceset[intersect(rownames(example_rho), rownames(sceset)),]

cellassign核心步驟

# cellassign object
# 獲取sizefactor
s <- sizeFactors(example_sce)

fit <- cellassign(exprs_obj = example_sce,
                  marker_gene_info = example_rho,
                  s = s,
                  learning_rate = 1e-2,
                  shrinkage = TRUE,
                  verbose = FALSE)
print(fit)
#> A cellassign fit for 500 cells, 10 genes, 2 cell types with 0 covariates
#>             To access cell types, call celltypes(x)
#>             To access cell type probabilities, call cellprobs(x)

使用celltypes函數(shù)最大似然法估計(jì)(MLE)細(xì)胞類型:

print(head(celltypes(fit)))
#> [1] "Group1" "Group2" "Group2" "Group1" "Group1" "Group1"

以及所有MLE參數(shù)使用mleparams:

print(str(mleparams(fit)))
#> List of 9
#>  $ delta  : num [1:10, 1:2] 2.32 0 2.5 2.9 2.89 ...
#>   ..- attr(*, "dimnames")=List of 2
#>   .. ..$ : chr [1:10] "Gene186" "Gene205" "Gene269" "Gene526" ...
#>   .. ..$ : chr [1:2] "Group1" "Group2"
#>  $ beta   : num [1:10, 1] 0.487 -0.255 -1.016 1.195 1.476 ...
#>   ..- attr(*, "dimnames")=List of 2
#>   .. ..$ : chr [1:10] "Gene186" "Gene205" "Gene269" "Gene526" ...
#>   .. ..$ : NULL
#>  $ phi    : num [1:500, 1:10, 1:2] 1.86 1.87 1.86 1.86 1.86 ...
#>  $ gamma  : num [1:500, 1:2] 1.00 1.56e-145 1.01e-43 1.00 1.00 ...
#>   ..- attr(*, "dimnames")=List of 2
#>   .. ..$ : NULL
#>   .. ..$ : chr [1:2] "Group1" "Group2"
#>  $ mu     : num [1:500, 1:10, 1:2] 22.6 80.9 11.5 15.5 15.8 ...
#>  $ a      : num [1:10(1d)] 1.03 1.08 1.13 1.19 1.26 ...
#>  $ theta  : num [1:2(1d)] 0.472 0.528
#>   ..- attr(*, "dimnames")=List of 1
#>   .. ..$ : chr [1:2] "Group1" "Group2"
#>  $ ld_mean: num 1
#>  $ ld_var : num 0.531
#> NULL

我們還可以使用cellprobs函數(shù)可視化賦值的概率,該函數(shù)返回每個(gè)細(xì)胞和細(xì)胞類型的概率矩陣:

pheatmap::pheatmap(cellprobs(fit))
image

最后,由于這是模擬數(shù)據(jù),我們可以檢查與真實(shí)組值的一致性:

print(table(example_sce$Group, celltypes(fit)))
#>
#>          Group1 Group2
#>   Group1    236      0
#>   Group2      0    264

腫瘤微環(huán)境Marker基因示例

對(duì)于人腫瘤微環(huán)境中的常見(jiàn)細(xì)胞類型,cellassign包中提供了一組示例標(biāo)記。

標(biāo)記基因可用于以下細(xì)胞類型:

  • B cells

  • T cells

  • Cytotoxic T cells

  • Monocyte/Macrophage

  • Epithelial cells

  • Myofibroblasts

  • Vascular smooth muscle cells

  • Endothelial cells

這些可以通過(guò)調(diào)用進(jìn)行訪問(wèn):

data(example_TME_markers)

注意這是兩列marker的列表:

names(example_TME_markers)
#> [1] "symbol"  "ensembl"

ensembl 包含基因符號(hào):

lapply(head(example_TME_markers$ensembl, n = 4), head, n = 4)
#> $`B cells`
#>               VIM             MS4A1             CD79A             PTPRC
#> "ENSG00000026025" "ENSG00000156738" "ENSG00000105369" "ENSG00000081237"
#>
#> $`T cells`
#>               VIM               CD2              CD3D              CD3E
#> "ENSG00000026025" "ENSG00000116824" "ENSG00000167286" "ENSG00000198851"
#>
#> $`Cytotoxic T cells`
#>               VIM               CD2              CD3D              CD3E
#> "ENSG00000026025" "ENSG00000116824" "ENSG00000167286" "ENSG00000198851"
#>
#> $`Monocyte/Macrophage`
#>               VIM              CD14            FCGR3A              CD33
#> "ENSG00000026025" "ENSG00000170458" "ENSG00000203747" "ENSG00000105383"

要將這些與cellassign一起使用,我們可以通過(guò)單元格類型矩陣將它們轉(zhuǎn)換為二進(jìn)制標(biāo)記:

marker_mat <- marker_list_to_mat(example_TME_markers$ensembl)

marker_mat[1:3, 1:3]
#>                 B cells T cells Cytotoxic T cells
#> ENSG00000010610       0       1                 0
#> ENSG00000026025       1       1                 1
#> ENSG00000039068       0       0                 0

重要的是:?jiǎn)渭?xì)胞實(shí)驗(yàn)或輸入基因表達(dá)矩陣應(yīng)該是相應(yīng)的子集,以匹配標(biāo)記輸入矩陣的行,例如, 如果sce是具有ensembl ID作為rownames的SingleCellExperiment,則調(diào)用:

# 對(duì)scater對(duì)象進(jìn)行篩選
sce_marker <- sce[intersect(rownames(marker_mat), rownames(sce)),]

局限性

1.CellAssign適用于標(biāo)記基因已經(jīng)非常明確的條件下,未知的細(xì)胞類型或細(xì)胞狀態(tài)可能是不可見(jiàn)的;2.作者在兩種不同細(xì)胞類型中的相同標(biāo)記的中等或高表達(dá)之間沒(méi)有先驗(yàn)區(qū)分。

更多單細(xì)胞操作

運(yùn)行環(huán)境

sessionInfo()
#> R version 3.6.0 (2019-04-26)
#> Platform: x86_64-apple-darwin15.6.0 (64-bit)
#> Running under: macOS Mojave 10.14
#>
#> Matrix products: default
#> BLAS:   /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib
#>
#> locale:
#> [1] en_CA.UTF-8/en_CA.UTF-8/en_CA.UTF-8/C/en_CA.UTF-8/en_CA.UTF-8
#>
#> attached base packages:
#> [1] parallel  stats4    stats     graphics  grDevices utils     datasets
#> [8] methods   base
#>
#> other attached packages:
#>  [1] SingleCellExperiment_1.6.0  SummarizedExperiment_1.14.0
#>  [3] DelayedArray_0.10.0         BiocParallel_1.18.0
#>  [5] GenomicRanges_1.36.0        GenomeInfoDb_1.20.0
#>  [7] cellassign_0.99.11          pheatmap_1.0.12
#>  [9] matrixStats_0.54.0          edgeR_3.26.5
#> [11] org.Hs.eg.db_3.8.2          AnnotationDbi_1.46.0
#> [13] IRanges_2.18.1              S4Vectors_0.22.0
#> [15] Biobase_2.44.0              BiocGenerics_0.30.0
#> [17] limma_3.40.2                magrittr_1.5
#> [19] BiocStyle_2.12.0
#>
#> loaded via a namespace (and not attached):
#>  [1] pkgload_1.0.2          bit64_0.9-7            jsonlite_1.6
#>  [4] assertthat_0.2.1       BiocManager_1.30.4     blob_1.1.1
#>  [7] GenomeInfoDbData_1.2.1 yaml_2.2.0             remotes_2.1.0
#> [10] sessioninfo_1.1.1      pillar_1.4.2           RSQLite_2.1.1
#> [13] backports_1.1.4        lattice_0.20-38        glue_1.3.1
#> [16] reticulate_1.12        digest_0.6.20          RColorBrewer_1.1-2
#> [19] XVector_0.24.0         colorspace_1.4-1       plyr_1.8.4
#> [22] htmltools_0.3.6        Matrix_1.2-17          pkgconfig_2.0.2
#> [25] devtools_2.0.2         bookdown_0.11          zlibbioc_1.30.0
#> [28] purrr_0.3.2            scales_1.0.0           processx_3.4.0
#> [31] whisker_0.3-2          tibble_2.1.3           usethis_1.5.1
#> [34] withr_2.1.2            cli_1.1.0              crayon_1.3.4
#> [37] memoise_1.1.0          evaluate_0.14          ps_1.3.0
#> [40] fs_1.3.1               pkgbuild_1.0.3         tools_3.6.0
#> [43] prettyunits_1.0.2      stringr_1.4.0          munsell_0.5.0
#> [46] locfit_1.5-9.1         callr_3.3.0            compiler_3.6.0
#> [49] rlang_0.4.0            grid_3.6.0             RCurl_1.95-4.12
#> [52] rstudioapi_0.10        bitops_1.0-6           base64enc_0.1-3
#> [55] rmarkdown_1.13         testthat_2.1.1         gtable_0.3.0
#> [58] DBI_1.0.0              R6_2.4.0               tfruns_1.4
#> [61] dplyr_0.8.3            knitr_1.23             tensorflow_1.13.1
#> [64] bit_1.1-14             rprojroot_1.3-2        desc_1.2.0
#> [67] stringi_1.4.3          Rcpp_1.0.1             tidyselect_0.2.5
#> [70] xfun_0.8

對(duì)單細(xì)胞轉(zhuǎn)錄組感興趣的話,不妨留意一下我們將在北京召開(kāi)的單細(xì)胞轉(zhuǎn)錄組數(shù)據(jù)整合分析專題(11月29號(hào)-12月01號(hào)):

10X登錄納斯達(dá)克,首日大漲35%,市值49億的技術(shù)你還不會(huì)?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,530評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,407評(píng)論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,981評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,759評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,204評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,415評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,955評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,782評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,983評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,222評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,650評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,892評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,675評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,967評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容