本博客介绍过 Affy芯片的处理方法 ,其中所使用的软件包有一定的局限性,无法读取和分析一些新版Affy芯片。本文介绍oligo软件包的处理方法以解决这些问题。oligo软件包并不是新出现的软件包,只因新类型芯片的不断推出,关注它的用户越来越多。而且,除了用于Affy芯片处理外,oligo软件包还可处理NimbleGen芯片。

oligo处理芯片的原理和其他方法相同,难点在最后一步:从探针到基因注释的转换。


1 准备工作

1.1 数据下载

本文还是以Affy芯片为例,介绍oligo软件包处理芯片数据的方法。所用数据集为NCBI GSE72154,可通过HTTP或FTP下载原始数据文件。建议使用FTP下载,登录ftp.ncbi.nlm.nih.gov站点,在/geo/datasets下找到GSE72154子目录后全部下载。下载的目录中包含matrix、miniml、soft和suppl四个子目录。

1.2 软件包安装

oligo是bioconductor软件包,可以通过下面语句安装:

source("https://bioconductor.org/biocLite.R")
biocLite("oligo")

2 文件读取与信息修改

oligo读取芯片原始数据文件的函数为 read.celfilesread.xysfiles (NimbleGen芯片),可以直接读取压缩文件,一张芯片对应一个文件。使用FTP下载后CEL文件位于suppl子目录下,把GSE72154_RAW.tar解压缩为gz文件或CEL文件即可。

library(oligo)
data.dir <- "GSE72154/suppl/"
(celfiles <- list.files(data.dir, "\\.gz$"))

## [1] "GSM1856253_Bohmer_685-3_Ler-0_Rep1_AraGene-1-1-st.CEL.gz"
## [2] "GSM1856254_Bohmer_685-4_Ler-0_Rep2_AraGene-1-1-st.CEL.gz"
## [3] "GSM1856255_Bohmer_685-1_wrky43_Rep1_AraGene-1-1-st.CEL.gz"
## [4] "GSM1856256_Bohmer_685-2_wrky43_Rep2_AraGene-1-1-st.CEL.gz"

data.raw <- read.celfiles(filenames = file.path(data.dir, celfiles))

## Reading in : GSE72154/suppl//GSM1856253_Bohmer_685-3_Ler-0_Rep1_AraGene-1-1-st.CEL.gz
## Reading in : GSE72154/suppl//GSM1856254_Bohmer_685-4_Ler-0_Rep2_AraGene-1-1-st.CEL.gz
## Reading in : GSE72154/suppl//GSM1856255_Bohmer_685-1_wrky43_Rep1_AraGene-1-1-st.CEL.gz
## Reading in : GSE72154/suppl//GSM1856256_Bohmer_685-2_wrky43_Rep2_AraGene-1-1-st.CEL.gz


read.celfiles 函数读取数据的过程中会检查系统中是否已安装相应的芯片注释软件包,没有安装的话将有警告。如果在读取的过程中没有自动安装相应注释软件包,请手动安装后再重新读取数据。

本例含4张芯片,文件名上面代码已列出,含野生型和突变体各两个重复。样品名称默认为文件名,需简单修改:

treats <- strsplit("Ler Ler wrky wrky", " ")[[1]]
(snames <- paste(treats, 1:2, sep = ""))

## [1] "Ler1"  "Ler2"  "wrky1" "wrky2"

sampleNames(data.raw) <- snames
pData(data.raw)$index <- treats
sampleNames(data.raw)

## [1] "Ler1"  "Ler2"  "wrky1" "wrky2"

pData(data.raw)

##       index
## Ler1    Ler
## Ler2    Ler
## wrky1  wrky
## wrky2  wrky

样品名称与芯片文件必需对应,不能有重复;pData的index数据表示处理类型。

3 探针水平分析

原始芯片数据读入后应简单评估一下芯片的质量,这在 其他文章 中介绍过,oligo中也提供了很多方法,如果样品重复量足够,boxplot是比较直观的方法:

fit1 <- fitProbeLevelModel(data.raw)
boxplot(fit1, names = NA, col = as.factor(treats))
legend("topright", legend = unique(treats), fill = as.factor(unique(treats)),box.col = NA, bg = "white", inset = 0.01)

当然也可以使用MAplot:

par(mfrow = c(2, 2))
MAplot(data.raw[, 1:4], pairs = FALSE)

4 表达量计算

含背景处理、归一化和表达量计算三个步骤,可选组合方法很多。下面就用通用的三合一处理函数rma一步完成:

data.eset <- rma(data.raw)

## Background correcting
## Normalizing
## Calculating Expression

得到eset类型的数据,用exprs函数可以提取其中的表达量矩阵:

data.exprs <- exprs(data.eset)
str(data.exprs)

##  num [1:38408, 1:4] 6.52 6.67 6.52 6.21 7.07 ...
##  - attr(*, "dimnames")=List of 2
##   ..$ : chr [1:38408] "13320001" "13320003" "13320005" "13320007" ...
##   ..$ : chr [1:4] "Ler1" "Ler2" "wrky1" "wrky2"

head(data.exprs)

##              Ler1     Ler2    wrky1    wrky2
## 13320001 6.515240 6.975158 6.163749 6.121993
## 13320003 6.670580 6.816606 5.808836 5.653102
## 13320005 6.522566 7.396850 7.011411 6.604062
## 13320007 6.206310 6.538738 5.477303 6.572429
## 13320009 7.071985 7.015605 6.426396 6.932439
## 13320011 6.558686 6.333987 6.670292 6.277999

5 P/A过滤

目的是去除“不表达”的基因/探针数据,使用paCalls函数,选取p值小于0.05的探针:

xpa <- paCalls(data.raw)
head(xpa)

##           Ler1       Ler2       wrky1       wrky2
## 7  0.477083333 0.80416667 0.327083333 0.689583333
## 8  0.550619835 0.73347107 0.786157025 0.361570248
## 11 0.327731092 0.01890756 0.231092437 0.189075630
## 14 0.005138746 0.01130524 0.005138746 0.005138746
## 17 0.057851240 0.07231405 0.045454545 0.027892562
## 20 0.013360740 0.01027749 0.051387461 0.006166495

AP <- apply(xpa, 1, function(x) any(x < 0.05))
xids <- as.numeric(names(AP[AP]))
head(xids)

## [1] 11 14 17 20 28 42

计算后发现P/A结果和表达量分析结果所用的探针名称是不一样的,需要使用探针信息进行转换。getProbeInfo函数可以获取相关信息:

pinfo <- getProbeInfo(data.raw)
head(pinfo)

##   fid man_fsetid
## 1   7   13507007
## 2   8   13379105
## 3  11   13402401
## 4  14   13363588
## 5  17   13492405
## 6  20   13488138

两类id转换后进行筛选:

fids <- pinfo[pinfo$fid %in% xids, 2]
head(fids)

## [1] "13402401" "13363588" "13492405" "13488138" "13349578" "13529865"

nrow(data.exprs)

## [1] 38408

data.exprs <- data.exprs[rownames(data.exprs) %in% fids, ]
nrow(data.exprs)

## [1] 35697

第一个语句筛选出表达基因的探针ID,第四个语句用筛选出的ID过滤掉不表达的基因/探针。

6 获取差异表达探针

下面使用的limma方法,更多方法请参考本博客 其他文章 。先根据样品名称、类型和顺序构建试验设计矩阵:

library(limma)
(design <- model.matrix(~0 + treats))

##   treatsLer treatswrky
## 1         1          0
## 2         1          0
## 3         0          1
## 4         0          1
## attr(,"assign")
## [1] 1 1
## attr(,"contrasts")
## attr(,"contrasts")$treats
## [1] "contr.treatment"

colnames(design) <- gsub("treats", "", colnames(design))
rownames(design) <- snames
design

##       Ler wrky
## Ler1    1    0
## Ler2    1    0
## wrky1   0    1
## wrky2   0    1
## attr(,"assign")
## [1] 1 1
## attr(,"contrasts")
## attr(,"contrasts")$treats
## [1] "contr.treatment"

然后将试验设计矩阵应用于表达量数据(exprs)或eset数据,获取拟合模型:

fit1 <- lmFit(data.exprs, design)
## fit1 <- lmFit(data.eset, design)

接下来进行试验处理组间的比较。因为只有两组样品,只可能是突变体和野生型间的比较:

contrast.matrix <- makeContrasts("wrky-Ler", levels = design)
fit2 <- contrasts.fit(fit1, contrast.matrix)
fit2 <- eBayes(fit2)

使用topTable函数获取表达变化倍数和相关统计值:

limma.all <- topTable(fit2, coef = 1, adjust.method = "fdr", number = 3e+05)
limma.fc2 <- topTable(fit2, coef = 1, adjust.method = "fdr", lfc = 1, number = 3e+05)
nrow(limma.all)

## [1] 35697

nrow(limma.fc2)

## [1] 1028

head(limma.fc2)

##             logFC   AveExpr        t      P.Value  adj.P.Val        B
## 13356037 4.540665 10.780301 39.28527 1.070928e-06 0.03822893 3.571807
## 13348341 4.206080  6.004308 31.68465 2.710592e-06 0.04838000 3.402196
## 13348348 3.569355  5.319289 21.22435 1.522879e-05 0.09541435 2.882561
## 13400731 3.029046  6.347611 20.99470 1.595751e-05 0.09541435 2.863891
## 13474474 3.259238  5.847156 20.82997 1.650674e-05 0.09541435 2.850205
## 13454438 2.750208  4.778045 19.55321 2.165705e-05 0.09541435 2.735128

topTable函数中可以直接使用p.value产生进行p值过滤,但由于本数据集生物学重复数太少,上面代码仅用表达变化倍数进行过滤。number参数用于限定结果的最大行数。

7 探针到基因的转换

有多种方法,下面介绍两种。

7.1 方法1:使用芯片注释文件

每版芯片都会有专门文件对探针进行说明,这些文件多数是公开的。前面通过NCBI FTP下载GEO芯片数据集时已提到matrix、miniml、soft和suppl四个子目录。miniml和soft目录都包含有平台相关的信息文件,其中soft目录下的GSE72154_family.soft.gz文件含有表头,可以使用该文件:

ff <- "GSE72154/soft/GSE72154_family.soft.gz"
nn <- grep("^[^#!^]", readLines(ff))[1] - 1
pfinfo <- read.table(ff, sep = "\t", quote = "", header = TRUE, skip = nn, fill = TRUE)
colnames(pfinfo)

##  [1] "ID"                    "seqname"
##  [3] "strand"                "start"
##  [5] "stop"                  "total_probes"
##  [7] "gene_assignment"       "mrna_assignment"
##  [9] "GB_ACC"                "ORF"
## [11] "SPOT_ID"               "swissprot"
## [13] "GO_biological_process" "GO_cellular_component"
## [15] "GO_molecular_function" "protein_domains"
## [17] "crosshyb_type"         "category"

可以看到表格各列所包含的内容。现阶段我们只需要ID和ORF列,即探针编号和它们所检测的mRNA。提取信息后做一些必要的处理

pfinfo <- pfinfo[, c(1, 10)]
pfinfo$ORF <- toupper(pfinfo$ORF)
## 删除重复信息
pfinfo <- pfinfo[!duplicated(pfinfo), ]
## 删除非mRNA探针
pfinfo <- pfinfo[pfinfo$ORF != "", ]
rownames(pfinfo) <- pfinfo$ID
nrow(pfinfo)

## [1] 20657

得到以上基本信息后就可以添加到差异表达列表中。首先去除没有mRNA信息的探针:

result1 <- limma.fc2[rownames(limma.fc2) %in% pfinfo$ID, ]
nrow(result1)

## [1] 214

把AGI信息添加到表达列表,保存表格文件即可:

result1$agi <- pfinfo[rownames(result1), 2]
head(result1)

##              logFC   AveExpr         t      P.Value  adj.P.Val        B
## 13356037  4.540665 10.780301  39.28527 1.070928e-06 0.03822893 3.571807
## 13474474  3.259238  5.847156  20.82997 1.650674e-05 0.09541435 2.850205
## 13454438  2.750208  4.778045  19.55321 2.165705e-05 0.09541435 2.735128
## 13335452 -2.729114  9.397657 -18.21499 2.935056e-05 0.09541435 2.594936
## 13376651 -2.154874  7.127874 -16.55810 4.414524e-05 0.09541435 2.387110
## 13464968  1.667566  8.680761  14.94084 6.845745e-05 0.09541435 2.138016
##                  agi
## 13356037 AT1G67105.1
## 13474474 AT4G27940.1
## 13454438 AT3G27473.1
## 13335452 AT1G03880.1
## 13376651 AT1G47540.2
## 13464968 AT4G02555.1

write.csv(result1, "results.fc2.1.csv")

7.2 方法2:使用基因组特征文件

芯片厂商提供的探针注释文件有可能过时。如分析十多年前的试验芯片,一些基因的注释可能有很大变化。但不管怎么样,探针在基因组上的位置信息应该不会有太大的差异,应用基因组进行比对总不会大错。

Bioconductor提供了专门用于处理基因组特征文件的类和函数,相关的gff格式文件可以从各种途径免费获取。本例使用的是TAIR网站下载的拟南芥基因组特征文件。

library("rtracklayer")
ath.gff <- readGFFAsGRanges("TAIR10_GFF3_genes.gff")
class(ath.gff)

## [1] "GRanges"
## attr(,"package")
## [1] "GenomicRanges"

读入数据存储为GRanges类,其数据结构可以使用str函数查看,相关的基础知识已在 R/BioC序列处理之五:Rle和Ranges 一文中介绍过。GRanges的每一条信息都包含了很多内容,这里仅关心外显子、UTR和miRNA相关的序列:

xtype <- as.character(ath.gff@elementMetadata@listData$type)
unique(xtype)

##  [1] "chromosome"                "gene"
##  [3] "mRNA"                      "protein"
##  [5] "exon"                      "five_prime_UTR"
##  [7] "CDS"                       "three_prime_UTR"
##  [9] "miRNA"                     "tRNA"
## [11] "ncRNA"                     "pseudogene"
## [13] "pseudogenic_transcript"    "pseudogenic_exon"
## [15] "transposable_element_gene" "mRNA_TE_gene"
## [17] "snoRNA"                    "snRNA"
## [19] "rRNA"

sels <- grepl("exon|utr|miRNA", xtype, ignore.case = TRUE)
ath.gff <- ath.gff[sels]

接下来获取探针在基因组上的位置信息。这一步可以用前面的芯片注释文件数据,也可以使用随CEL文件读取时载入的数据。类似数据在前面P/A过滤部分已经用到过,但这里要提取更多的信息:

availProbeInfo(data.raw)

## $pmfeature
## [1] "fid"    "fsetid" "atom"   "x"      "y"
##
## $featureSet
## [1] "fsetid"        "strand"        "start"         "stop"
## [5] "exon_id"       "crosshyb_type" "level"         "chrom"
## [9] "type"
##
## $core_mps
## [1] "meta_fsetid"           "transcript_cluster_id" "fsetid"

pinfo <- getProbeInfo(data.raw, field = strsplit("fid chrom strand start stop exon_id"," ")[[1]])
head(pinfo)

##   fid man_fsetid strand    start     stop   exon chrom
## 1   7   13507007      0 11107381 11107491 884614  chr5
## 2   8   13379105      1 19981386 19981486 778732  chr1
## 3  11   13402401      0 16131514 16131647 798181  chr2
## 4  14   13363588      1  1457201  1457469 765883  chr1
## 5  17   13492405      1 15589898 15590906 872458  chr4
## 6  20   13488138      1 11944077 11944154 868967  chr4

在应用数据前做一些必要的处理:

pinfo <- pinfo[grepl("^chr", pinfo$chrom), ]
pinfo$chrom <- gsub("^c", "C", pinfo$chrom)
pinfo$strand <- sapply(pinfo$strand, FUN = function(x) {if (x == 0)"+" else "-"
})

然后构建探针对应的GRanges类对象:

xrange <- GRanges(seqnames = pinfo$chrom, ranges = IRanges(start = pinfo$start,end = pinfo$stop, names = pinfo$man_fsetid), strand = pinfo$strand)

正式比对并将产生探针-基因注释数据:

xlap <- findOverlaps(xrange, ath.gff, select = "all", type = "within")
anno <- data.frame(fid = names(xrange)[queryHits(xlap)], agi = ath.gff@elementMetadata$Parent@unlistData[subjectHits(xlap)])
anno <- anno[!duplicated(anno), ]
head(anno)

##        fid         agi
## 1 13507007 AT5G29044.1
## 2 13379105 AT1G53541.1
## 3 13402401 AT2G38544.1
## 4 13363588 AT1G05070.1
## 5 13492405 AT4G32290.1
## 6 13488138 AT4G22740.1

有部分探针可能和基因组上多个基因对应,有必要进行合并,或者舍弃这部分数据:

anno <- aggregate(agi ~ fid, FUN = c, data = anno, simplify = TRUE)
anno$agi <- sapply(anno$agi, FUN = paste, collapse = ";")
rownames(anno) <- anno$fid

最后合并数据:

result2 <- limma.fc2[rownames(limma.fc2) %in% anno$fid, ]
result2$agi <- sapply(anno[rownames(result2), "agi"], FUN = paste, collapse = ";")
nrow(limma.fc2)

## [1] 1028

nrow(result2)

## [1] 464

write.csv(result2, "results.fc2.2.csv")

为什么最后得到的基因数量比前一种方法要多?自己分析原因吧。

如果需要进行GO/KEGG途径富集分析,还应导出芯片中的“表达”基因:

xagis <- anno[anno$fid %in% fids, "agi"]
writeLines(xagis, "results.present.genes.txt")

8 SessionInfo

print(sessionInfo(), locale = FALSE)

## R version 3.3.3 (2017-03-06)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Debian GNU/Linux 8 (jessie)
##
## attached base packages:
## [1] stats4    parallel  stats     graphics  grDevices utils     datasets
## [8] methods   base
##
## other attached packages:
##  [1] rtracklayer_1.34.2       GenomicRanges_1.26.4
##  [3] GenomeInfoDb_1.10.3      limma_3.30.13
##  [5] pd.aragene.1.0.st_3.12.0 DBI_0.6
##  [7] RSQLite_1.1-2            oligo_1.38.0
##  [9] Biostrings_2.42.1        XVector_0.14.1
## [11] IRanges_2.8.2            S4Vectors_0.12.2
## [13] Biobase_2.34.0           oligoClasses_1.36.0
## [15] BiocGenerics_0.20.0      zblog_0.1.0
## [17] knitr_1.15.1
##
## loaded via a namespace (and not attached):
##  [1] Rcpp_0.12.10               BiocInstaller_1.24.0
##  [3] formatR_1.4                highr_0.6
##  [5] bitops_1.0-6               iterators_1.0.8
##  [7] tools_3.3.3                zlibbioc_1.20.0
##  [9] digest_0.6.12              bit_1.1-12
## [11] evaluate_0.10              memoise_1.0.0
## [13] preprocessCore_1.36.0      lattice_0.20-35
## [15] ff_2.2-13                  Matrix_1.2-8
## [17] foreach_1.4.3              stringr_1.2.0
## [19] affxparser_1.46.0          grid_3.3.3
## [21] BiocParallel_1.8.1         XML_3.98-1.5
## [23] magrittr_1.5               GenomicAlignments_1.10.1
## [25] Rsamtools_1.26.1           codetools_0.2-15
## [27] splines_3.3.3              SummarizedExperiment_1.4.0
## [29] KernSmooth_2.23-15         stringi_1.1.3
## [31] RCurl_1.95-4.8             affyio_1.44.0


作者: ZGUANG@LZU

Created: 2017-03-27 一 18:03

使用oligo软件包处理芯片数据相关推荐

  1. Bioconductor分析基因芯片数据第五章

    使读者初步了解使用Bionconductor完成基因芯片预处理的流程 接着详细讲解戏弄i按预处理和数据分析等内容 最后深入了解实际工作中会遇到的芯片处理问题以及如何用学到的只是解决问题 目的:掌握芯片 ...

  2. 芯片数据分析笔记【05】 | 处理芯片数据的R包

    芯片数据分析笔记[01] | 基因芯片的基本原理 芯片数据分析笔记[02] | 芯片数据库 芯片数据分析笔记[03] | GEO数据库使用教程及在线数据分析工具 芯片数据分析笔记[04] | Arra ...

  3. stm32 iic接口 进入busy_STM32通过IIC接口读取JY61模块MPU6050陀螺仪芯片数据核心程序...

    1 简述 最近,想学角度融合算法在网上买一个JY61的模块.他们家的模块用起来还不错.模块分为串口通讯和IIC通讯的.串口读取数据他们家有例程,我就不说了.想分享给大家这个模块的IIC是怎么去读取MP ...

  4. (转)基因芯片数据GO和KEGG功能分析

    随着人类基因组计划(Human Genome Project)即全部核苷酸测序的即将完成,人类基因组研究的重心逐渐进入后基因组时代(Postgenome Era),向基因的功能及基因的多样性倾斜.通过 ...

  5. r语言怎么把txt数据变成一个Rdata格式_甲基化芯片数据下载如何读入到R里面

    数据是一切的开始,前面我们介绍了一些背景知识,主要是理解什么是DNA甲基化,为什么要检测它,以及芯片和测序两个方向的DNA甲基化检测技术.具体介绍在:甲基化的一些基础知识,也了解了甲基化芯片的一般分析 ...

  6. ATECC508A芯片开发笔记(九):加密读写508芯片数据的流程及相应设置

    目录 ATECC508A芯片开发笔记(九):加密读写508芯片数据的流程及相应设置 1.Encrypted Read 1.1 Standard Encrypted Read Flow 1.2 Simp ...

  7. 骁龙835(MSM8998)芯片数据参考

    骁龙835(MSM8998)芯片数据参考 啊哈哈,分享完MTK的芯片资料,现在来个高通骁龙835芯片的资料吧,高通的资料在网上也比较少,相对来说,高通资料比MTK的保密程度更高,但怎么会难倒我们闯客网 ...

  8. 高通MSM8998芯片数据资料参考

    高通MSM8998芯片数据资料参考 今日分享是高通MSM8998芯片的基础知识,现在分享是比较基础的资料,还有其他的项目案例和参考资料找个时间再分享出来,资料都在闯客网技术论坛上,也是可以免费下载的, ...

  9. 高通MDM9628芯片数据参考

    高通MDM9628芯片数据参考 啊哈哈,分享完MTK的芯片资料,现在来个MDM9628芯片的资料吧,只是想把所有的资料都分享出来给大家,所有高通的芯片资料都在闯客网技术论坛了,加群也可以获取资料,高通 ...

  10. 使用python中TsTables 软件包追加写入数据出现“pandas.tseries has no attribute‘index‘”的问题

    球球今天下午在用jupyter使用TsTables 软件包追加写入数据的时候用了一行代码:%time ts.append(df),可是直接报错pandas.tseries has no attribu ...

最新文章

  1. 浙大博士整理的计算机视觉学习路线(含时间建议分配)
  2. C# DataTable 转换成ListT
  3. matlab在图像上画出来的矩形框如何变成可托动的_计算机基础系列:源代码如何被计算机执行...
  4. Spring Boot系列——7步集成RabbitMQ
  5. Js Array数组ES5/ES6常用方法
  6. 全球及中国软件外包行业“十四五”展望发展建议及创新布局战略报告2021-2027年
  7. OpenCV使用MultiTracker
  8. vim 格式化json
  9. android 如何使用LaunchMode
  10. Pinterest:Android系统上的视频管理
  11. mqtt js 中乱码_Vue.js 中的 v-cloak 指令——Vue学习之路
  12. Android VNC Server New
  13. WCF技术实现基于角色的访问控制
  14. 【BZOJ4247】挂饰,又一个奇特的背包
  15. linux sh 必要,Linux Shell学习之基础篇(不适合学习,仅为本人笔记)
  16. P2799国王的魔镜
  17. 如何调整转场时间和移动转场效果
  18. 使用装机软件后,删除开机启动项的方法
  19. IT十年人生过客-十二-痛并快乐着
  20. 怎么用c语言让电脑定时开关机,电脑定时开关机,教您怎么设置电脑定时开关机...

热门文章

  1. 读《淘宝产品十年事》-怎样成为一名出色的产品经理
  2. java毕业设计小小银动漫网站源码+lw文档+mybatis+系统+mysql数据库+调试
  3. 学习基于springboot的java分布式中间件-Redis(3) redis之缓存穿透等典型问题
  4. 用LeapFTP上传文件碰到的问题及解决办法
  5. C# 中文简体中文繁体转换_ChineseConverter
  6. 如何面对大容量的数据存储
  7. System Toolkit 3.3.3 中文版 系统维护工具箱
  8. 计算机网络速度怎么改,怎么让电脑网速变快? 公用网络怎么变快
  9. 腾讯手机管家(android2.3),腾讯手机管家3.4 Android发布_软件资讯软件快报-中关村在线...
  10. windows11错误代码0x0000011b怎么解决? 0x0000011b问题的相应解决办法