# Subtract list with part of the same list

This may be a silly question but if I have a long list (let's call it data)such as this:

https://pastebin.com/QCAKwZ2P

How can I make that list of a certain lenght?. In particular I want to subtract the entire list with a part of the same list but since they are of different length I cannot do it.

I would like to do something like this:

data-Select[data, 50 <= #[[1]] <= 105 &] but since data is of higher lenght than Select[data, 50 <= #[[1]] <= 105 &] it gives me an error. Is there a way around this?

Thank you.

EDIT:

I have been trying to do it with Interpolation like this:

dat1 = Select[data, 60 <= First[#] <= 140 &];
dat2 = Select[data, 10 <= First[#] <= 65 &];
fit1 = Interpolation[dat1];
fit2 = Interpolation[dat2];

fit1[#] - fit2[#] &;


but doing it with interpolation in this way is not working for me either perhaps because the interpolations are of different sizes as well?.

• I’m not sure I even follow the logic here. What do you expect to happen? If it was 1 part of the list, sure, then you just do a ConstantArray which is the length of the list you’re pulling from, but this seems like there will be a sequence that is found, and the operation of subtracting part of the list from the whole list honestly does not make any sense to me. Maybe I am misinterpreting, but how would the elements be distributed? This does not seem standard hence my requests for clarification. Jun 22, 2020 at 2:05
• @CATrevillian Thanks for your comment. I simply mean if there is a way to subtract the entire list with a part of the list. For example, I was trying to use something like data[[;; ;; 50]] to get essentially the same that you will get from data (taking every 50 points or so) and at the same time reducing the lenght of data resulting in a lenght of 58 in this case. I just hoping to find something similar in which I can reduce the lenght of data such as I can subtract some other part of the same data. I hope that makes more sense.
– John
Jun 22, 2020 at 2:16
• I was thinking that another approach could be perhaps fitting part of the data to an interpolation function and simply subtract data-part of data (from the interpolation).
– John
Jun 22, 2020 at 2:19
• If you want to perform addition operations (subtraction is adding the negated value) of multiple lists, they will need to be the same length. Say you have Range[10] and you want to subtract {7, 8, 9} from the entire list, what do you expect to happen—that is, what is your expected output? Please note that the word subtract is not the same as remove. Jun 22, 2020 at 2:22
• @CATrevillian yes, I understand that if they are different lenghts they simply cannot be subtracted. That's why my example with data[[;; ;; 50]]] (which reduces the lenght of data while more of less keeping the overall trend of the data) and also my example of perhaps fitting the entire data and then there should be a way to subtract a part of the fitting of data with the entire fitting of data, no?
– John
Jun 22, 2020 at 2:29

TimeSeries provides a fairly direct approach to this:

data = Import["https://pastebin.com/raw/QCAKwZ2P", "Package"];

dat1 = Select[data, 60 <= First[#] <= 140 &];
dat2 = Select[data, 10 <= First[#] <= 65 &];

ts2 = TimeSeries[dat2] ~TimeSeriesRescale~ {60, 140};

dat3 = {#, #2 - ts2[#]} & @@@ dat1;

ListPlot[{dat1, dat2, dat3}]


See also TimeSeriesResample.

ts2raw = TimeSeries[dat2];

datX = Array[{#, ts2raw@#} &, Length @ dat1, MinMax[First /@ dat2]];


Closely related but allowing for nonuniform sampling:

{t1, t2} = {dat1, dat2}[[All, All, 1]];
{m1, m2} = MinMax /@ {t1, t2};
ts2 = TimeSeries[dat2];

datY = {#, ts2@#} & /@ Rescale[t1, m1, m2];


Or:

{ts1, ts2} = TimeSeries /@ {dat1, dat2};
times = TimeSeriesRescale[ts1, MinMax @ ts2["Times"]]["Times"];

tsX = TimeSeriesResample[ts2, {times}]

• Thank you very much Mr. Wizard!!!
– John
Jun 22, 2020 at 16:22
• Mr Wizard. I think in your code there is a similar comment than what I did to C.E. Shouldn't dat2 and ts2 be the same when plotted together?. One should be simply the rescalation of the other but they are different
– John
Jun 22, 2020 at 18:02
• @John Certainly they shouldn't cover the same x-range; that's the whole point of rescaling? Or perhaps I misunderstand? What exactly are you seeing? Jun 22, 2020 at 18:56
• Mr. Wizard, for instance if I plottem such as: ListPlot[{dat2, ts2, dat1}] then you can see that dat2 and ts2 are very different. What I wanted is for instance for dat2 and ts2 to be equal with the only different being that one is rescaled in a way that they cover the same range but one is every 10 points or so so that it has the same length that dat1 but still cover the same range
– John
Jun 22, 2020 at 19:26
• @John Please see the addendum in my answer; is datX what you are looking for? Jun 22, 2020 at 19:55

Here's how to get the same result as Mr. Wizard with your interpolation approach (perhaps there is a slight difference in the result, but the idea is the same):

dat1 = Select[data, 60 <= First[#] <= 140 &];
dat2 = Select[data, 10 <= First[#] <= 65 &];
interp1 = Interpolation[dat1];
interp2 = Interpolation[dat2];

rescaled = Quiet@Table[{0, interp2[t]}, {t, Most@Subdivide[10., 65., Length[dat1]]}];
ListLinePlot[{dat1, dat2, dat1 - rescaled}]


• Aweome! Thank you C.E !
– John
Jun 22, 2020 at 16:21
• I think the reason the code gives a slightly different result than Mr.Wizard is that in your code if you compare interp2 and rescaled they are different and they should be the same as one is simply the rescaled of the other, no?
– John
Jun 22, 2020 at 17:57
• To follow up the idea if I use for instance ListLinePlot[{interp2, rescaled, dat1}] you can see that dat2 and rescaled are very very different and in fact rescaled goes to about 1300 in the x-axis rather than to only from 10 to 73.
– John
Jun 22, 2020 at 18:12
• @John I made a small mistake, but it didn't impact the result a whole lot. Just a small ~1 unit offset along the x-axis. I fixed it now. Jun 22, 2020 at 19:05
• @John Well then I understood it correctly, but as I said, it's really a very trivial change. I would rather see that you figured it out yourself so that you understand the solution. You only have to change a single character in my solution to get the equivalent of Mr. Wizard's datX. Jun 22, 2020 at 20:16
ts = TimeSeries @ data;

{window1, window2} = {{60, 140}, {10, 65}};

{ts1, ts2} = TimeSeriesWindow[ts, #] & /@ {window1, window2};

dif12 = ts1 - TimeSeriesRescale[ts2, window1];

ListLinePlot[{ ts, dif12}]


• Thank you very much kglr !!!
– John
Jun 23, 2020 at 3:21

Use Select directly to get the list you want, changing the selection predicate from what you have to accomplish this. Replace < by > or vice versa.

• I don’t think that answers OP’s question. I believe they have asked a similar question wherein that method was given as an answer. Subtract=/=remove, at least with how I read this. Jun 22, 2020 at 2:14
• Possibly. I read subtraction as as a way to make the list shorter given original post. But perhaps not correct interpretation on my part. Jun 22, 2020 at 3:21