python - 循环遍历 R 中的 .dat 文件并仅提取特定数据作为列
问题描述
我的本地驱动器中有 900 多个文件夹,每个文件夹都有一个 .dat 扩展文件。我想遍历每个文件夹以访问其中的文件以仅获取特定数据并将该数据写入新文件中。每个 .dat 文件看起来像这样 -
Authors:
# Pallavi Subhraveti
# Quang Ong
# Tim Holland
# Anamika Kothari
# Ingrid Keseler
# Ron Caspi
# Peter D Karp
# Please see the license agreement regarding the use of and distribution of
this file.
# The format of this file is defined at http://bioinformatics.ai.sri.com
# Version: 21.5
# File Name: compounds.dat
# Date and time generated: October 24, 2017, 14:52:45
# Attributes:
# UNIQUE-ID
# TYPES
# COMMON-NAME
# ABBREV-NAME
# ACCESSION-1
# ANTICODON
# ATOM-CHARGES
# ATOM-ISOTOPES
# CATALYZES
# CFG-ICON-COLOR
# CHEMICAL-FORMULA
# CITATIONS
# CODONS
# COFACTORS-OF
# MOLECULAR-WEIGHT
# MONOISOTOPIC-MW
[Data Chunk 1]
UNIQUE-ID - CPD0-1108
TYPES - D-Ribofuranose
COMMON-NAME - β-D-ribofuranose
ATOM-CHARGES - (9 -1)
ATOM-CHARGES - (6 1)
CHEMICAL-FORMULA - (C 5)
CHEMICAL-FORMULA - (H 14)
CHEMICAL-FORMULA - (N 1)
CHEMICAL-FORMULA - (O 6)
CHEMICAL-FORMULA - (P 1)
CREDITS - SRI
CREDITS - kaipa
DBLINKS - (CHEBI "10647" NIL |kothari| 3594051403 NIL NIL)
DBLINKS - (BIGG "37147" NIL |kothari| 3584718837 NIL NIL)
DBLINKS - (PUBCHEM "25200464" NIL |taltman| 3466375284 NIL NIL)
DBLINKS - (LIGAND-CPD "C01233" NIL |keseler| 3342798255 NIL NIL)
INCHI - InChI=1S/C5H14NO6P/c6-1-2-11-13(9,10)12-4-5(8)3-7/h5,7-8H,1-4,6H2,(H,9,10)
MOLECULAR-WEIGHT - 215.142
MONOISOTOPIC-MW - 216.0636987293
NON-STANDARD-INCHI - InChI=1S/C5H14NO6P/c6-1-2-11-13(9,10)12-4-5(8)3-7/h5,7-8H,1-4,6H2,(H,9,10)
SMILES - C(OP([O-])(OCC(CO)O)=O)C[N+]
SYNONYMS - sn-Glycero-3-phosphoethanolamine
SYNONYMS - 1-glycerophosphorylethanolamine\
[Data Chunk 2]
//
UNIQUE-ID - URIDINE
TYPES - Pyrimidine
....
....
每个文件中大约有 18000 行(查看 Notepad++ 中的数据)。现在我想创建一个新文件并只复制数据中的特定列。我只想将这些列复制到我新创建的文件中,文件应如下所示 -
UNIQUE-ID TYPES COMMON-NAME CHEMICAL-FORMULA BIGG ID CHEMSPIDER ID CAS ID CHEBI ID PUBCHEM ID MOLECULAR-WEIGHT MONOISOTOPIC-MW
CPD0-1108 D-Ribofuranose β-D-ribofuranose C5H14N1O6P1 37147 NA NA 10647 25200464 215.142 216.0636987293
URIDINE Pyrimidine ...
每个文件中的每个数据块不一定都有我需要的所有列的信息,这就是为什么我在我想要的输出表中提到那些列的 NA。虽然如果我在这些列中获得空白值完全没问题,因为我可以稍后单独处理这些空白。
这是包含数据的目录 -
File 1] -> C:\Users\robbie\Desktop\Organism_Data\aact1035194-hmpcyc\compounds.dat
File 2] -> C:\Users\robbie\Desktop\Organism_Data\aaph679198-hmpcyc\compounds.dat
File 3] -> C:\Users\robbie\Desktop\Organism_Data\yreg1002368-hmpcyc\compounds.dat
File 4] -> C:\Users\robbie\Desktop\Organism_Data\tden699187-hmpcyc\compounds.dat
...
...
我真的倾向于dir
在引用这篇文章的 R 中使用该函数,但是在编写代码时我很困惑在函数的模式参数中放入什么,因为有机体名称(文件夹名称)非常奇怪且不一致。
非常感谢获得所需输出的任何帮助。我正在考虑在 R 中执行此操作的方法,但如果我得到好的建议和在 python 中处理此问题的方法,我也愿意在 python 中尝试此操作。非常感谢您的帮助!
编辑:链接到数据 -数据
解决方案
一个文件
把它分解成几个合乎逻辑的动作:
text2chunks <- function(txt) {
chunks <- split(txt, cumsum(grepl("^\\[Data Chunk.*\\]$", txt)))
Filter(function(a) grepl("^\\[Data Chunk.*\\]$", a[1]), chunks)
}
chunk2dataframe <- function(vec, hdrs = NULL, sep = " - ") {
s <- stringi::stri_split(vec, fixed=sep, n=2L)
s <- Filter(function(a) length(a) == 2L, s)
df <- as.data.frame(setNames(lapply(s, `[[`, 2), sapply(s, `[[`, 1)),
stringsAsFactors=FALSE)
if (! is.null(hdrs)) df <- df[ names(df) %in% make.names(hdrs) ]
df
}
hdrs
是您要保留的列名的可选向量;如果未提供(或NULL
),则所有键/值对都作为列返回。
hdrs <- c("UNIQUE-ID", "TYPES", "COMMON-NAME")
使用数据(如下),我有lines
一个character
来自单个文件的向量:
head(lines)
# [1] "Authors:"
# [2] "# Pallavi Subhraveti"
# [3] "# Quang Ong"
# [4] "# Please see the license agreement regarding the use of and distribution of this file."
# [5] "# The format of this file is defined at http://bioinformatics.ai.sri.com"
# [6] "# Version: 21.5"
str(text2chunks(lines))
# List of 2
# $ 1: chr [1:5] "[Data Chunk 1]" "UNIQUE-ID - CPD0-1108" "TYPES - D-Ribofuranose" "COMMON-NAME - β-D-ribofuranose" ...
# $ 2: chr [1:6] "[Data Chunk 2]" "// something out of place here?" "UNIQUE-ID - URIDINE" "TYPES - Pyrimidine" ...
str(lapply(text2chunks(lines), chunk2dataframe, hdrs=hdrs))
# List of 2
# $ 1:'data.frame': 1 obs. of 3 variables:
# ..$ UNIQUE.ID : chr "CPD0-1108"
# ..$ TYPES : chr "D-Ribofuranose"
# ..$ COMMON.NAME: chr "β-D-ribofuranose"
# $ 2:'data.frame': 1 obs. of 3 variables:
# ..$ UNIQUE.ID : chr "URIDINE"
# ..$ TYPES : chr "Pyrimidine"
# ..$ COMMON.NAME: chr "β-D-ribofuranose or something"
最终产品:
dplyr::bind_rows(lapply(text2chunks(lines), chunk2dataframe, hdrs=hdrs))
# UNIQUE.ID TYPES COMMON.NAME
# 1 CPD0-1108 D-Ribofuranose β-D-ribofuranose
# 2 URIDINE Pyrimidine β-D-ribofuranose or something
由于您想在许多函数上迭代它,因此为此创建一个便利函数是有意义的:
text2dataframe <- function(txt) {
dplyr::bind_rows(lapply(text2chunks(txt), chunk2dataframe, hdrs=hdrs))
}
许多文件
未经测试,但应该可以工作:
files <- list.files(path="C:/Users/robbie/Desktop/Organism_Data/",
pattern="compounds.dat", recursive=TRUE, full.names=TRUE)
alldata <- lapply(files, readLines)
allframes <- lapply(alldata, text2dataframe)
oneframe <- dplyr::bind_rows(allframes)
笔记:
- 我使用
stringi::stri_split
而不是strsplit
仅仅为了方便的论点n=
;用几行额外的代码在基础 R 中做同样的事情并不难。 - 我使用它是
dplyr::bind_rows
因为它很好地处理了缺失的列和不同的顺序;底座rbind.data.frame
可以通过一些额外的努力/小心使用。 data.frame
-izing 事物往往会稍微调整列名,请注意。
数据:
# lines <- readLines("some_filename.dat")
fulltext <- 'Authors:
# Pallavi Subhraveti
# Quang Ong
# Please see the license agreement regarding the use of and distribution of this file.
# The format of this file is defined at http://bioinformatics.ai.sri.com
# Version: 21.5
# File Name: compounds.dat
# Date and time generated: October 24, 2017, 14:52:45
# Attributes:
# UNIQUE-ID
# TYPES
[Data Chunk 1]
UNIQUE-ID - CPD0-1108
TYPES - D-Ribofuranose
COMMON-NAME - β-D-ribofuranose
DO-NOT-CARE - 42
[Data Chunk 2]
// something out of place here?
UNIQUE-ID - URIDINE
TYPES - Pyrimidine
COMMON-NAME - β-D-ribofuranose or something
DO-NOT-CARE - 43
'
lines <- strsplit(fulltext, '[\r\n]+')[[1]]
推荐阅读
- html - 将一个圆圈居中放在 div 的中间
- angular - kendo-grid Angular 的页脚
- google-chrome-devtools - Chrome DevTools:文件失去与工作区的链接
- php - 不要通过模型从数据库中获取行,而是通过外观数据库获取它
- php - php解析错误与意外';' 在第 12 行,但没有错
- javascript - 如何在 C# 的类库中运行 npm 命令
- vue.js - vuex 模块无法将元素添加到根状态
- ios - 从相机捕获图像时内存泄漏
- android - Android 库模块的消费者必须添加类路径依赖项
- java - 使用 XML 配置进行 DAO 调用的 Spring 重试