What is the best way to subtract a single entry or a histogram of entries from another histogram?

I am using 5.30/04 with gcc.

I noticed that you cannot FillN with -1 to subtract an array of entries from a histogram, but I was not surprised since this method does not even have float support.

However, I was very surprised to find that using Fill(x,-1) also does not remove the entry from a histogram. I want to be able to subtract a value from a histogram. What are some ways of doing that?

I came across this question when I noticed that Add(TH1,-1) has a bug where it removes too many entries, and I need a method that works properly.

TH1F *h = new TH1F("h","h",500,-,1,1);
h->FillRandom("gaus");
for(int i=0 ; i<h->GetNbins() ; ++i) {
h->SetBinContent(i,h->GetBinContent(i)-1);
}

Hi pamputt,

The problem with that solution is that I would have to solve for the bin number every time I wanted to remove a specific value from the histogram. That is a lot of computation. Is there a way to automatically do that?

This is basically what is done by the Add method.

I have tried using Add(x,-1), however there seems to be a bug in 5.30 because this removes more entries than are in the histogram. I would prefer to use Add if it worked.

What is the code line that you use? What is “x”? The Add method allows only to either subtract two histograms or a function and a histogram.

I have tried both modes of Add:

    hist2->Add(hist1,-1.0);
    hist2->Add(hist2,hist1,1.0,-1.0);

Each of these results in a histogram which has more entries subtracted than are actually in hist1. (Meaning that if I then add hist1 back with +1, I end up with lost entries).

hist2->Add(hist1,-1.0);

will remove the hist1 from the hist2

hist2->Add(hist2,hist1,1.0,-1.0);

will do the same. This is not what you want to do. If you only want to remove 1 to each bin of your histogram, see my previous reply

Oh, yes, that is exactly what I want to do. However, those commands do not remove hist1 from hist 2. In both cases, they remove hist1 and some additional entries from hist2. I am not sure if this is a known bug, or if there is a way to work around it.

Ah ok, sorry for the misunderstanding. So, I do not know whether it is a known bug, but you should use the latest version that may contain some bugfixes.
See ROOT 5.34/36 or 6.14/00

Note: In both example codes shown below, the histogram’s statistics will not be modified.

{
  TH1D *h = new TH1D("h", "h", 3, -1.5, 1.5); // create a test histogram
  h->Print("all");
  h->Fill(0., 1.); // fill one bin
  h->Print("all");
  double value = -10.; // what you want to "add"/"subtract" to/from all bins
#if 1 /* 0 or 1 */
  // ... including "underflow" and "overflow" bins
  Int_t i_f = 0, i_l = (h->GetNbinsX() + 1);
#else /* 0 or 1 */
  // ... excluding "underflow" and "overflow" bins
  Int_t i_f = 1, i_l = h->GetNbinsX();
#endif /* 0 or 1 */
  for (Int_t i = i_f; i <= i_l; i++) h->AddBinContent(i, value); // "add"
  h->Print("all");
  for (Int_t i = i_f; i <= i_l; i++) h->AddBinContent(i, -value); // "subtract"
  h->Print("all");
}
{
  TH1D *h = new TH1D("h", "h", 3, -1.5, 1.5); // create a test histogram
  h->Print("all");
  h->Fill(0., 1.); // fill one bin
  h->Print("all");
  double value = -10.; // what you want to "add"/"subtract" to/from all bins
  // "find" the default preexisting "polynomial of the order 0" function
  TF1 *f = ((TF1*)(gROOT->GetFunction("pol0"))); // a "constant value"
  // set the same "range" as the histogram ...
#if 1 /* 0 or 1 */
  // ... including "underflow" and "overflow" bins
  f->SetRange( h->GetBinLowEdge(0),
               ( h->GetBinLowEdge(h->GetNbinsX() + 1) +
                 h->GetBinWidth(h->GetNbinsX() + 1) ) );
#else /* 0 or 1 */
  // ... excluding "underflow" and "overflow" bins
  f->SetRange(h->GetBinLowEdge(1), h->GetBinLowEdge(h->GetNbinsX() + 1));
  // f->SetRange(h->GetXaxis()->GetXmin(), h->GetXaxis()->GetXmax());
#endif /* 0 or 1 */
  f->SetParameter(0, value); // set the "parameter 0" = value
  h->Add(f, 1.); // "add" function to the histogram
  h->Print("all");
  h->Add(f, -1.); // "subtract" function from the histogram
  h->Print("all");
  f->SetParameter(0, 1.); // set the "parameter 0" = 1.
  h->Add(f, value); // "add" function to the histogram
  h->Print("all");
  h->Add(f, -value); // "subtract" function from the histogram
  h->Print("all");
}

Unfortunately, my system administrator cannot upgrade ROOT right now. So I have to figure out a way to get my version to subtract histograms if possible.

I think my thread title is misleading. What I want to subtract is either 1) a single value or 2) a second histogram. The first use of Add involving functions does not help since I am not using any functions. I have checked the underflow and overflow bins and I could not get them to account for the extra subtraction. There is a note in the Add manual that specifies that there could be unusual behavior when the weight is less than 0, but it is not fully explained.

    num1 = hist1->GetEntries();
    printf("%i\n",num1);

    num2 = hist2->GetEntries();
    printf("%i\n",num2);
    
    hist1->Add(hist2, -1.0);

    num3 = hist1->GetEntries();
    printf(" = %i\n",num3);

136312535
10295
136302225

The result is wrong. This is also what I get with the third add method specifying 1.0 as the weight for hist1.

I have tested counting the entries with GetEntries, Integral, GetEffectiveEntries, and manually counting all of the histogram contents with GetBinContent, and adjusting the range from 1|nbins to 0|nbins+1.

I have not been able to restore the number of entries in the histogram after an Add(X,-1), Add(X,+1) operation using Add2 or Add3, in any of these tests.

How do you ensure that Add,-1 followed by an Add+1 restores the original histogram?

Roughly speaking, the value returned by TH1::GetEntries is how many times you called TH1::Fill and/or TH1::SetBinContent so, it can only “increase”. You can use TH1::SetEntries, if you want to modify it.

You can call TH1::ResetStats if you want to “reset” histogram’s statistics (including the “number of entries”) and replace it with values calculates from the actual bins’ content. Unfortunately, how everything gets recalculated (including the “number of entries”) depends also on the actual TH1::Sumw2 setting (i.e. whether the histogram has / hasn’t associated error bars).

Note: In principle, TH1::GetEffectiveEntries and TH1::Integral do not depend on TH1::GetEntries.

I have tried using ResetStats, but the error I am finding persists. I think it may not be possible to maintain the correct number of entries in a histogram through adding a subtracting.

So I am giving up on using this. Thanks for the advice everyone.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.