text: user1771: I have two bed-like files:
  File1
  chr1     1     10    .    1    Sample1
  chr1    20    180    .    1    Sample1
  chr1     1      5    .    1    Sample2
  chr1    70    100    .    1    Sample3
  
  File2 (reference)
  chr1     1     5     .    0 
  chr1     5    20     .    1
  chr1    50   120     .   -1
  
  I'd like to find a way to apply a function (in my case a subtraction) between the first file and the second, using the second as a reference, and producing a results file containing also the indication of the sample name.
  For example, in my case the results file would be:
  chr1     1      5    .    1    Sample1
  chr1     5     10    .    0    Sample1
  chr1    20     50    .    1    Sample1
  chr1    50    120    .    2    Sample1
  chr1   120    180    .    1    Sample1
  chr1     1      5    .    1    Sample2
  chr1    70    100    .    2    Sample3
  
  I was thinking about implementing it in pandas, but it would be long to do and probably not so efficient. I looked for bedmap but it seems to me that this operation can be carried on (with the sum operation) only within a single file during aggregation, not between two different bed files. So maybe it is not the right tool to use in this case.
  Also, it would be important in the final file to retain the sample name.
  
  user776: You could munge your first file into a BED5 file:
  $ awk -vOFS="\t" '{ print $1, $2, $3, $6, $5 }' /tmp/f1.bed | sort-bed - > /tmp/f1.bed5
  
  Sort the second file, if necessary:
  $ sort-bed /tmp/f2.unknownSort.bed5 > /tmp/f2.bed5
  
  Take the union of the two sorted files:
  $ bedops -u /tmp/f1.bed5 /tmp/f2.bed5 > /tmp/union.bed
  
  Here's what the union looks like:
  chr1    1       5       .       0       
  chr1    1       5       Sample2 1
  chr1    1       10      Sample1 1
  chr1    5       20      .       1
  chr1    20      180     Sample1 1
  chr1    50      120     .       -1
  chr1    70      100     Sample3 1
  
  We have one name scheme for reference element IDs (.) and a second name scheme for sample IDs (Sample*). 
  We will exploit this difference in name schemes when we apply operations in a certain order. For this example, we will subtract a reference element score from a sample element score.
  We can partition the union, mapping the disjoint elements back to the unioned set:
  $ bedops --partition /tmp/union.bed | bedmap --echo --echo-map-id --echo-map-score --delim '\t' - /tmp/union.bed
  chr1    1   5   .;Sample2;Sample1   0.000000;1.000000;1.000000
  chr1    5   10  Sample1;.   1.000000;1.000000
  chr1    10  20  .   1.000000
  chr1    20  50  Sample1 1.000000
  chr1    50  70  Sample1;.   1.000000;-1.000000
  chr1    70  100 Sample1;.;Sample3   1.000000;-1.000000;1.000000
  chr1    100 120 Sample1;.   1.000000;-1.000000
  chr1    120 180 Sample1 1.000000
  
  Each of the fourth and fifth columns are semi-colon-delimited strings. Each element is ordered by the order in which it is discovered in a bedmap operation. 
  Both columns have the same ordering or same one-to-one correspondence of ID to signal score. This is very useful, because we can turn these into a pair of ordered arrays and apply some logic, depending on the answer we want back.
  For example, here is some awk logic to parse those two strings and subtract a reference element score from a sample element score:
  $ bedops --partition /tmp/union.bed \
      | bedmap --echo --echo-map-id --echo-map-score --delim '\t' - /tmp/union.bed \
      | awk -vFS="\t" -vOFS="\t" \
          '{ \
               i=split($4,a,";"); \
               j=split($5,b,";"); \
               if ((i==1) && (a[i]==".")) { pass; } \
               else { \
                   for (k=1; k<=i; k++) { \
                       if (a[k]==".") { refIdx=k; } \
                   } \
                   for (k=1; k<=i; k++) { \
                       if (k!=refIdx) { print $0, ".", b[k]-b[refIdx], a[k]; } \
                   } \
               } \
           }' \
      | cut -f1-3,6-8 \
      | sort-bed - \
      > answer.bed
  
  The file answer.bed will look like this:
  chr1    1   5   .   1   Sample1
  chr1    1   5   .   1   Sample2
  chr1    5   10  .   0   Sample1
  chr1    20  50  .   1   Sample1
  chr1    50  70  .   2   Sample1
  chr1    70  100 .   2   Sample1
  chr1    70  100 .   2   Sample3
  chr1    100 120 .   2   Sample1
  chr1    120 180 .   1   Sample1
  
  This partitioning of intervals is different from the one in your question. Perhaps this is due to how you partitioned your set. In any case, perhaps this would give you an idea of how to apply custom operations over a disjoint partitioning.
  The main idea is that this part of the awk script finds the score associated with the reference file ("File2"):
  for (k=1; k<=i; k++) {
      if (a[k]==".") { refIdx=k; }
  }
  
  Any index other than refIdx corresponds to a Sample* element. That means we can do operations between Sample* scores and the specific reference score.
  We also leave out mappings where a reference score does not associate with any Sample* element:
  if ((i==1) && (a[i]==".")) { pass; }
  
  Thus, all the operations are always between a pairing of a sample and the mapped reference element.
  The cut and sort-bed statements at the end just clean up the result so that you get something that looks like what you are expecting at the end, which is also sorted correctly and ready to use for downstream set operations.
  
original_text: 1771: <p>I have two bed-like files:</p>
  
  <p><strong>File1</strong></p>
  
  <pre><code>chr1     1     10    .    1    Sample1
  chr1    20    180    .    1    Sample1
  chr1     1      5    .    1    Sample2
  chr1    70    100    .    1    Sample3
  </code></pre>
  
  <p><strong>File2</strong> (reference)</p>
  
  <pre><code>chr1     1     5     .    0 
  chr1     5    20     .    1
  chr1    50   120     .   -1
  </code></pre>
  
  <p>I'd like to find a way to apply a function (in my case a subtraction) between the first file and the second, using the second as a reference, and producing a results file containing also the indication of the sample name.
  For example, in my case the results file would be:</p>
  
  <pre><code>chr1     1      5    .    1    Sample1
  chr1     5     10    .    0    Sample1
  chr1    20     50    .    1    Sample1
  chr1    50    120    .    2    Sample1
  chr1   120    180    .    1    Sample1
  chr1     1      5    .    1    Sample2
  chr1    70    100    .    2    Sample3
  </code></pre>
  
  <p>I was thinking about implementing it in pandas, but it would be long to do and probably not so efficient. I looked for <a href="https://bedops.readthedocs.io/en/latest/content/reference/statistics/bedmap.html" rel="nofollow noreferrer">bedmap</a> but it seems to me that this operation can be carried on (with the sum operation) only within a single file during aggregation, not between two different bed files. So maybe it is not the right tool to use in this case.</p>
  
  <p>Also, it would be important in the final file to retain the sample name.</p>
   776: <p>You could munge your first file into a BED5 file:</p>
  
  <pre><code>$ awk -vOFS="\t" '{ print $1, $2, $3, $6, $5 }' /tmp/f1.bed | sort-bed - &gt; /tmp/f1.bed5
  </code></pre>
  
  <p>Sort the second file, if necessary:</p>
  
  <pre><code>$ sort-bed /tmp/f2.unknownSort.bed5 &gt; /tmp/f2.bed5
  </code></pre>
  
  <p>Take the union of the two sorted files:</p>
  
  <pre><code>$ bedops -u /tmp/f1.bed5 /tmp/f2.bed5 &gt; /tmp/union.bed
  </code></pre>
  
  <p>Here's what the union looks like:</p>
  
  <pre><code>chr1    1       5       .       0       
  chr1    1       5       Sample2 1
  chr1    1       10      Sample1 1
  chr1    5       20      .       1
  chr1    20      180     Sample1 1
  chr1    50      120     .       -1
  chr1    70      100     Sample3 1
  </code></pre>
  
  <p>We have one name scheme for reference element IDs (<code>.</code>) and a second name scheme for sample IDs (<code>Sample*</code>). </p>
  
  <p>We will exploit this difference in name schemes when we apply operations in a certain order. For this example, we will subtract a reference element score from a sample element score.</p>
  
  <p>We can partition the union, mapping the disjoint elements back to the unioned set:</p>
  
  <pre><code>$ bedops --partition /tmp/union.bed | bedmap --echo --echo-map-id --echo-map-score --delim '\t' - /tmp/union.bed
  chr1    1   5   .;Sample2;Sample1   0.000000;1.000000;1.000000
  chr1    5   10  Sample1;.   1.000000;1.000000
  chr1    10  20  .   1.000000
  chr1    20  50  Sample1 1.000000
  chr1    50  70  Sample1;.   1.000000;-1.000000
  chr1    70  100 Sample1;.;Sample3   1.000000;-1.000000;1.000000
  chr1    100 120 Sample1;.   1.000000;-1.000000
  chr1    120 180 Sample1 1.000000
  </code></pre>
  
  <p>Each of the fourth and fifth columns are semi-colon-delimited strings. Each element is ordered by the order in which it is discovered in a <code>bedmap</code> operation. </p>
  
  <p>Both columns have the same ordering or same one-to-one correspondence of ID to signal score. This is very useful, because we can turn these into a pair of ordered arrays and apply some logic, depending on the answer we want back.</p>
  
  <p>For example, here is some <code>awk</code> logic to parse those two strings and subtract a reference element score from a sample element score:</p>
  
  <pre><code>$ bedops --partition /tmp/union.bed \
      | bedmap --echo --echo-map-id --echo-map-score --delim '\t' - /tmp/union.bed \
      | awk -vFS="\t" -vOFS="\t" \
          '{ \
               i=split($4,a,";"); \
               j=split($5,b,";"); \
               if ((i==1) &amp;&amp; (a[i]==".")) { pass; } \
               else { \
                   for (k=1; k&lt;=i; k++) { \
                       if (a[k]==".") { refIdx=k; } \
                   } \
                   for (k=1; k&lt;=i; k++) { \
                       if (k!=refIdx) { print $0, ".", b[k]-b[refIdx], a[k]; } \
                   } \
               } \
           }' \
      | cut -f1-3,6-8 \
      | sort-bed - \
      &gt; answer.bed
  </code></pre>
  
  <p>The file <code>answer.bed</code> will look like this:</p>
  
  <pre><code>chr1    1   5   .   1   Sample1
  chr1    1   5   .   1   Sample2
  chr1    5   10  .   0   Sample1
  chr1    20  50  .   1   Sample1
  chr1    50  70  .   2   Sample1
  chr1    70  100 .   2   Sample1
  chr1    70  100 .   2   Sample3
  chr1    100 120 .   2   Sample1
  chr1    120 180 .   1   Sample1
  </code></pre>
  
  <p>This partitioning of intervals is different from the one in your question. Perhaps this is due to how you partitioned your set. In any case, perhaps this would give you an idea of how to apply custom operations over a disjoint partitioning.</p>
  
  <p>The main idea is that this part of the <code>awk</code> script finds the score associated with the reference file ("File2"):</p>
  
  <pre><code>for (k=1; k&lt;=i; k++) {
      if (a[k]==".") { refIdx=k; }
  }
  </code></pre>
  
  <p>Any index other than <code>refIdx</code> corresponds to a <code>Sample*</code> element. That means we can do operations between <code>Sample*</code> scores and the specific reference score.</p>
  
  <p>We also leave out mappings where a reference score does not associate with any <code>Sample*</code> element:</p>
  
  <pre><code>if ((i==1) &amp;&amp; (a[i]==".")) { pass; }
  </code></pre>
  
  <p>Thus, all the operations are always between a pairing of a sample and the mapped reference element.</p>
  
  <p>The <code>cut</code> and <code>sort-bed</code> statements at the end just clean up the result so that you get something that looks like what you are expecting at the end, which is also sorted correctly and ready to use for downstream set operations.</p>
  