XSLT преобразовывают эффективность

Из описания вашего вопроса я постараюсь дать ответ в меру своих возможностей. Кажется, у нас есть несколько файлов на каждом шаге. Я предлагаю использовать внешний цикл 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)
9
задан raven 22 October 2008 в 22:24
поделиться

5 ответов

Для обнаружения, когда запустить новый раздел я сделал это:

<xsl:if test="@TheFirstCol>preceding-sibling::*[1]/@TheFirstCol"

Это могло вызывать много или повторение?

Определенно. Алгоритм, который Вы выбрали, является O (N2) и был бы очень медленным с достаточным числом одноуровневых элементов, независимо от языка реализации.

Вот эффективный алгоритм с помощью ключей:

Solution1:

<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('&#xA;',@c1)"/>

       <xsl:for-each select="key('kC1Value',@c1)">
         <xsl:value-of select="'&#xA;'"/>
         <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:

Solution2:

<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('&#xA;',@c1)"/>

       <xsl:for-each select="key('kC1Value',@c1)">
         <xsl:value-of select="'&#xA;'"/>
         <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 минут.

3
ответ дан 4 December 2019 в 13:50
поделиться

Одна вещь, которой состоит в том мировая проверка, если Ваш XSLT делает поиски в другие части XML-документа много, т.е. Вы находитесь в одном узле контекста и поиске значение в другой части документа или даже другого документа. При выполнении этого, это может поразить производительность довольно трудно, и необходимо рассмотреть использование xsl:key и ключевой функции для этого. Это говорит процессору реализовывать быстрый индекс поиска на рассматриваемых данных.

Я однажды создавал XSLT, который занял 8 часов для выполнения (с большим количеством перекрестных ссылок), и переключающийся для использования ключи дал ему крупное повышение скорости.

2
ответ дан 4 December 2019 в 13:50
поделиться

Я не знаком с реализациями.NET, но существует несколько вещей, которые можно сделать в целом для ускорения обработки больших документов:

  • Избегайте использования "//" в выражениях XPath, если не абсолютно необходимо.
  • Если Вам только нужны первое или только элемент, который соответствует выражению XPath, используйте" [1]" спецификатор, например, "//iframe[1]". Много процессоров реализуют оптимизацию для этого.
  • Каждый раз, когда возможно, при контакте с огромным входом XML, видят, можно ли разработать решение на основе синтаксического анализатора на основе потоков (как SAX) вместо основанного на DOM синтаксического анализатора.
5
ответ дан 4 December 2019 в 13:50
поделиться

Обычно, если Вы видите нелинейное увеличение во время обработки по сравнению с входным размером, необходимо подозревать код больше, чем платформа. Но так как проблема уходит, когда инструмент компилируется с.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, если Вы добавляете шаблонное соответствие, которое внезапно уничтожает производительность, прокомментируйте каждый блок в шаблоне. Затем не прокомментируйте один блок за один раз, тестируя время обработки каждое повторение, пока Вы не находите блок, который вызывает проблему.

4
ответ дан 4 December 2019 в 13:50
поделиться

После поиска Вашей проблемы я нашел КБ в Microsoft об этом. Вы видите его здесь.

Они говорят, что XSLT преобразовывают в.NET 1, имеет некоторые проблемы с производительностью и что они могут предложить быстрое исправление.

Если Вы хотите попытаться диагностировать проблему, существует профилировщик XSLT, доступный здесь.

Иначе Вы видите, какие ссылки дан на веб-сайте Microsoft для оптимизации проблем скорости с XSLT (ссылка).

1
ответ дан 4 December 2019 в 13:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: