ENH: Series.explode_range minimal implementation - WIP
State: closed

This is work in progress

- [ ] closes #39630 
- [ ] tests added / passed
- [ ] Ensure all linting tests pass, see [here](https://pandas.pydata.org/pandas-docs/dev/development/contributing.html#code-standards) for how to run them
- [ ] whatsnew entry


Labels:

Comments:
Looks like failures are not in my code...
```
 >>> start = pd.Series([0, 2])
        >>> start
        0    0
        1    2
        dtype: int64
        >>> stop = pd.Series([3, 2])
        >>> stop
        0    3
        1    2
        dtype: int64
        >>> start.explode_range(stop)
        0    0
        0    1
        0    2
        dtype: int64
        >>> start.explode_range(stop, 1) # now start point is skipped
        0    1
        0    2
        dtype: int64
        >>> start.explode_range(stop, 1, 1) # now start skipped but stop included
        0    1
        0    2
        0    3
        dtype: int64
        >>> start.explode_range(stop, 0, 1) # both start and stop included
        0    0
        0    1
        0    2
        0    3
        1    2
        dtype: int64
```
My main usage is something like overlap joins for integer ranges (could be day or week number or item count or item versions)
but I believe any place where you have discrete ranges you need to explode could be used.

e.g. one table with events of one type - week from week to and another table with over events week from week to I need to join/anti-join.

First I get week numbers from period[W-SAT] or similar... then I can explode_range both ranges and do the join or anti-join.




to be constructive: could you perhaps provide some more examples (might be good to have those be tests)
```
events1 = pd.DataFrame({
    'id1': [1, 2, 3],
    'start': [10, 27, 30],
    'stop': [15, 31, 31]
}).set_index('id1')

	start	stop
id1		
1	10	15
2	27	31
3	30	31

events2 = pd.DataFrame({
    'id2': [7, 8, 9],
    'start': [5, 25, 30],
    'stop': [12, 27, 31]
}).set_index('id2')

	start	stop
id2		
7	5	12
8	25	27
9	30	31

events1.start.explode_range(events1.stop)

id1
1    10
1    11
1    12
1    13
1    14
2    27
2    28
2    29
2    30
3    30
dtype: int64

events2.start.explode_range(events2.stop)


explode_range(events2.start, events2.stop)
id2
7     5
7     6
7     7
7     8
7     9
7    10
7    11
8    25
8    26
9    30
dtype: int64

explode_range(events1.start, events1.stop).reset_index().merge(
    explode_range(events2.start, events1.stop).reset_index()
).rename(columns={0: 'day'})

	id1	day	id2
0	1	10	7
1	1	11	7
2	1	12	7
3	1	13	7
4	1	14	7
5	2	27	8
6	2	28	8
7	2	29	8
8	2	30	8
9	2	30	9
10	3	30	8
11	3	30	9

```
What I actually do is more complicated because before join there is some extra processing and of course after, but this is basically gist of it.

left_shift/right_shift are for ranges being closed or not, separation between ranges or having at leas n common entries...
u can explode ranges using a range with RangeIndex and interaction / union

alt u can use merge_asof

-1 on any additional api
How do you do it?

I've tried couple things and either they did not work or required extrac object creation.
> How do you do it?
> 
> I've tried couple things and either they did not work or required extrac object creation.

could ask on StackOverflow, generally speaking that's the place for usage questions
> could ask on StackOverflow, generally speaking that's the place for usage questions

could save your time on responses like that and not answer at all.

I've searched Stack Overflow and answers to similar questions are not really efficient.
There is nothing in Pandas doc. I've searched Pandas issues.
I've put up some time on writing code and examples.

So instead of writing such answers you could've provide an example. Or add it to docs.

> So instead of writing such answers you could've provide an example. Or add it to docs.

this is not the purpose of the all volunteers who are here