Из описания вашего вопроса я постараюсь дать ответ в меру своих возможностей. Кажется, у нас есть несколько файлов на каждом шаге. Я предлагаю использовать внешний цикл for с функцией внутреннего применения, которую вы можете использовать для чтения и выполнения желаемых преобразований.
initial_dir <- "directory to the folder with the initial data"
data_dir <- "directory to the folder containing the secondary data"
file_names <- c("lots of file names") #1: Insert any number of files here from which to read numbers for the bed_chr_[nr].bed files here
#loop over the initial files
for(i in file_names){
file <- paste0(initial_dir,"/", i)
x <- fread(file, header = TRUE)
#combine secondary path and name
secondary_files <- paste0(data_dir,"/bed_chr_", unique(x[, [Insert the column for which the value for the bed_chr_[nr].bed files are in the intitial variable here <--]), ".bed") #2: insert column name (note i added unique)
#Apply the desired transformation
xx <- lapply(secondary_files, function(z){ #lapply will apply the 'function' to each element in 'secondary_files'.
b <- fread(z)
data.table( #apply the transformation and return a table to the list
x %>%
inner_join(b, by = c("rs_id" = "V4")) %>%
select(gene_id, chr, rs_id, pvalue_G, pvalue_E, V2, V3) %>%
unite(snp, chr, V3, remove = FALSE)
)
}) #after the lapply has run xx contains all the tables from the bed_chr_[numbers].bed files. All will have been read.
#xx is now a list that contains all the table after applying
#We can combine them using data.tables 'rbindlist'
x_final <- rbindlist(xx)
#now we can use data.tables 'fwrite' to output the table to a file
names(x_final)[6] <- "pvalue"
fwrite(x_final, "ready_plot_sg.txt", quote = "F", col.names = TRUE, row.names = FALSE) #here all the bed_chr_[numbers].bed files will be output into a single combined file
}
Примечания: я использовал paste0 вместо paste. Они обе объединяют строки в R, разница в том, что paste0
имеет стандартный аргумент sep = ""
, где paste
вставляет пробел по умолчанию lapply
применяет функцию к списку, вектору или аналогичному и выводит результат в виде список. Можно использовать также vapply
или sapply
, но это не обязательно даст вам список результатов, который в этом случае желателен для использования rbindlist
без каких-либо дополнительных параметров. В целях моего примера я предположил, что в вашей трансформации b не было ошибок.
::: Edit ::: Из нового фрагмента, добавленного опрашивающим, я в специальном случае перепишу опубликованный мною код, чтобы показать, как они должны были быть объединены:
require(dplyr);library(data.table);require(magrittr); require(tidyr)
initial_dir <- "" #The base directory in 'edit' was none ("merged_plot_RGL" is in working directory)
data_dir <- "anika/bed"
file_names <- c("merged_plot_RGL") #1: I inserted the merged_plot_RGL, as this contains the labels for the 'bed' files.
#Note: This loop is now redundant as we only have 1 file. But for illustration it was kept (i will only take on 'merged_plot_RGL' as a value)
for(i in file_names){
file <- i #2: Sets current file to merged_plot_RGL. paste0 removed as intial_dir was empty ("")
x <- fread(file, header = TRUE) #3: loads in merged_plot_RGL as a data.table
#4: combine secondary path and name (Note: I extract the number from x's chr column)
secondary_files <- paste0(data_dir,"/bed_chr_", unique(x[, chr]), ".bed")
#5: Apply the desired transformation via lapply (Note: xx becomes a list of transformed data from the bed files)
xx <- lapply(secondary_files, function(z){
b <- fread(z) #5.1: First read in the .bed file (done 1 by 1)
data.table( #5.2: apply the transformation and return a table to the list
x %>%
inner_join(b, by = c("rs_id" = "V4")) %>% #Note: Questioneers error came
select(gene_id, chr, rs_id, pvalue_G, pvalue_E, V2, V3) %>%
unite(snp, chr, V3, remove = FALSE)
)
})
#Note: After the lapply has run, and read in each .bed file, xx is now a list of .bed data tables that have been transformed by inner join, select and unite.
#6: We can combine them using data.tables 'rbindlist'
x_final <- rbindlist(xx)
#7: now we can use data.tables 'fwrite' to output the table to a file
names(x_final)[6] <- "pvalue"
fwrite(x_final, "ready_plot_sg.txt", quote = "F", col.names = TRUE, row.names = FALSE)
}
[1113 ] ::: Edit 2 ::: более короткая версия с более легким чтением ошибок.
require(dplyr);library(data.table);require(magrittr); require(tidyr)
data_dir <- "anika/bed"
file_names <- c("merged_plot_RGL")
x <- fread("merged_plot_RGL", header = TRUE)
secondary_files <- paste0(data_dir,"/bed_chr_", unique(x[, chr]), ".bed")
bed_files <- lapply(secondary_files, fread)
xx <- rbindlist(bed_files)
xx2 <- x %>%
inner_join(xx, by = c("rs_id" = "V4"))
xx3 <- xx2 %>%
select(gene_id, chr, rs_id, pvalue_G, pvalue_E, V2, V3)
xx4 <- xx3 %>%
unite(snp, chr, V3, remove = FALSE)
names(xx4)[6] <- "pvalue"
fwrite(xx4, "ready_plot_sg.txt", quote = "F", col.names = TRUE, row.names = FALSE)
Для обнаружения, когда запустить новый раздел я сделал это:
<xsl:if test="@TheFirstCol>preceding-sibling::*[1]/@TheFirstCol"
Это могло вызывать много или повторение?
Определенно. Алгоритм, который Вы выбрали, является O (N2) и был бы очень медленным с достаточным числом одноуровневых элементов, независимо от языка реализации.
Вот эффективный алгоритм с помощью ключей:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kC1Value" match="@c1" use="."/>
<xsl:template match="/">
<xsl:for-each select="*/x[generate-id(@c1) = generate-id(key('kC1Value',@c1)[1])]">
<xsl:value-of select="concat('
',@c1)"/>
<xsl:for-each select="key('kC1Value',@c1)">
<xsl:value-of select="'
'"/>
<xsl:for-each select="../@*[not(name()='c1')]">
<xsl:value-of select="concat(' ', .)"/>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
К сожалению, XslTransform (.Net 1.1) имеет известно неэффективную реализацию generate-id()
функция.
Следующее может быть быстрее с XslTransform:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kC1Value" match="@c1" use="."/>
<xsl:template match="/">
<xsl:for-each select="*/x[count(@c1 | key('kC1Value',@c1)[1]) = 1]">
<xsl:value-of select="concat('
',@c1)"/>
<xsl:for-each select="key('kC1Value',@c1)">
<xsl:value-of select="'
'"/>
<xsl:for-each select="../@*[not(name()='c1')]">
<xsl:value-of select="concat(' ', .)"/>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
При применении на следующий маленький XML-документ:
<t>
<x c1="1" c2="0" c3="0" c4="0" c5="0"/>
<x c1="1" c2="0" c3="1" c4="0" c5="0"/>
<x c1="1" c2="2" c3="0" c4="0" c5="0"/>
<x c1="1" c2="1" c3="1" c4="0" c5="0"/>
<x c1="2" c2="0" c3="0" c4="0" c5="0"/>
<x c1="2" c2="0" c3="1" c4="0" c5="0"/>
<x c1="2" c2="2" c3="0" c4="0" c5="0"/>
<x c1="2" c2="1" c3="1" c4="0" c5="0"/>
<x c1="3" c2="0" c3="0" c4="0" c5="0"/>
<x c1="3" c2="0" c3="1" c4="0" c5="0"/>
<x c1="3" c2="2" c3="0" c4="0" c5="0"/>
<x c1="3" c2="1" c3="1" c4="0" c5="0"/>
<x c1="3" c2="0" c3="0" c4="0" c5="0"/>
<x c1="3" c2="0" c3="1" c4="0" c5="0"/>
<x c1="3" c2="2" c3="0" c4="0" c5="0"/>
<x c1="3" c2="1" c3="1" c4="0" c5="0"/>
<x c1="4" c2="0" c3="0" c4="0" c5="0"/>
<x c1="4" c2="0" c3="1" c4="0" c5="0"/>
<x c1="4" c2="2" c3="0" c4="0" c5="0"/>
<x c1="4" c2="1" c3="1" c4="0" c5="0"/>
<x c1="5" c2="0" c3="0" c4="0" c5="0"/>
<x c1="5" c2="0" c3="1" c4="0" c5="0"/>
<x c1="5" c2="2" c3="0" c4="0" c5="0"/>
<x c1="5" c2="1" c3="1" c4="0" c5="0"/>
<x c1="5" c2="0" c3="0" c4="0" c5="0"/>
<x c1="5" c2="0" c3="1" c4="0" c5="0"/>
<x c1="6" c2="2" c3="0" c4="0" c5="0"/>
<x c1="6" c2="1" c3="1" c4="0" c5="0"/>
<x c1="6" c2="0" c3="0" c4="0" c5="0"/>
<x c1="6" c2="0" c3="1" c4="0" c5="0"/>
<x c1="6" c2="2" c3="0" c4="0" c5="0"/>
<x c1="6" c2="1" c3="1" c4="0" c5="0"/>
<x c1="7" c2="0" c3="0" c4="0" c5="0"/>
<x c1="7" c2="0" c3="1" c4="0" c5="0"/>
<x c1="7" c2="2" c3="0" c4="0" c5="0"/>
<x c1="7" c2="1" c3="1" c4="0" c5="0"/>
<x c1="8" c2="0" c3="0" c4="0" c5="0"/>
<x c1="8" c2="0" c3="1" c4="0" c5="0"/>
<x c1="8" c2="2" c3="0" c4="0" c5="0"/>
<x c1="8" c2="1" c3="1" c4="0" c5="0"/>
</t>
оба решения привели к требуемому результату:
1
0 0 0 0
0 1 0 0
2 0 0 0
1 1 0 0
2
0 0 0 0
0 1 0 0
2 0 0 0
1 1 0 0
3
0 0 0 0
0 1 0 0
2 0 0 0
1 1 0 0
0 0 0 0
0 1 0 0
2 0 0 0
1 1 0 0
4
0 0 0 0
0 1 0 0
2 0 0 0
1 1 0 0
5
0 0 0 0
0 1 0 0
2 0 0 0
1 1 0 0
0 0 0 0
0 1 0 0
6
2 0 0 0
1 1 0 0
0 0 0 0
0 1 0 0
2 0 0 0
1 1 0 0
7
0 0 0 0
0 1 0 0
2 0 0 0
1 1 0 0
8
0 0 0 0
0 1 0 0
2 0 0 0
1 1 0 0
От вышеупомянутого небольшого XML-файла я генерировал XML-файл 10 МБ путем копирования каждого элемента 6250 раз (использующий другое преобразование XSLT :)).
С XML-файлом 10 МБ и с XslCompiledTransform (.Net 2.0 +) эти два решения имели следующие разы преобразования:
Solution1: 3,3 секунды.
Solution2: 2,8 секунды.
С XslTransform (.Net 1.1) Solution2 работал в течение 1 622 секунд.; это составляет приблизительно 27 минут.
Одна вещь, которой состоит в том мировая проверка, если Ваш XSLT делает поиски в другие части XML-документа много, т.е. Вы находитесь в одном узле контекста и поиске значение в другой части документа или даже другого документа. При выполнении этого, это может поразить производительность довольно трудно, и необходимо рассмотреть использование xsl:key и ключевой функции для этого. Это говорит процессору реализовывать быстрый индекс поиска на рассматриваемых данных.
Я однажды создавал XSLT, который занял 8 часов для выполнения (с большим количеством перекрестных ссылок), и переключающийся для использования ключи дал ему крупное повышение скорости.
Я не знаком с реализациями.NET, но существует несколько вещей, которые можно сделать в целом для ускорения обработки больших документов:
Обычно, если Вы видите нелинейное увеличение во время обработки по сравнению с входным размером, необходимо подозревать код больше, чем платформа. Но так как проблема уходит, когда инструмент компилируется с.NET 2.0, все ставки выключены.
С XSLT трудно создать нелинейную кривую производительности, если Вы делаете весь свой парсинг с прямыми шаблонными соответствиями:
<xsl:template match="foo">
<!--OUTPUT-->
<xsl:apply-templates / >
<!--OUTPUT-->
</xsl:template>
<xsl:template match="bar">
<!--OUTPUT-->
<xsl:apply-templates / >
<!--OUTPUT-->
</xsl:template>
Обратите особое внимание на где угодно, Вы, возможно, обратились к <xsl:for-each>
для парсинга; шаблонные соответствия являются фактически всегда лучшим способом достигнуть того же результата.
Один способ диагностировать эту проблему производительности состоит в том, чтобы воссоздать Ваш XSLT одно шаблонное соответствие за один раз, тестируя время обработки после добавления каждого соответствия. Вы могли бы запустить с этого соответствия:
<xsl:template match="*">
<xsl:copy> <!--Copy node -->
<xsl:copy-of select="@*"/> <!--Copy node attributes -->
<xsl:apply-templates /> <!--Process children -->
</xsl:copy>
</xsl:template>
Это будет соответствовать и копировать каждый узел, по одному, к новому документу. Это не должно показывать нелинейное увеличение во время обработки по сравнению с входным размером (если он делает, затем проблема не с Вашим кодом XSLT).
Поскольку Вы воссоздаете свой XSLT, если Вы добавляете шаблонное соответствие, которое внезапно уничтожает производительность, прокомментируйте каждый блок в шаблоне. Затем не прокомментируйте один блок за один раз, тестируя время обработки каждое повторение, пока Вы не находите блок, который вызывает проблему.
После поиска Вашей проблемы я нашел КБ в Microsoft об этом. Вы видите его здесь.
Они говорят, что XSLT преобразовывают в.NET 1, имеет некоторые проблемы с производительностью и что они могут предложить быстрое исправление.
Если Вы хотите попытаться диагностировать проблему, существует профилировщик XSLT, доступный здесь.
Иначе Вы видите, какие ссылки дан на веб-сайте Microsoft для оптимизации проблем скорости с XSLT (ссылка).