Compressing time series by removing repeated samples
You want to keep points where the value for \$y\$ is different from either the preceding or succeeding value. So in NumPy you can write:

import numpy as np

def compress_2D_signal(x, y):
    """Compress signal y(x) by omitting repeated values for y.

    Takes a signal y(x) as two array-likes x and y. Returns the
    compressed signal y1(x1) as the tuple x1, y1, where y1 contains
    the first and last values of y, and values of y that are different
    from the preceeding or succeeding value, and x1 contains the
    corresponding values from x.

    """
    x, y = np.asarray(x), np.asarray(y)
    keep = np.empty_like(x, dtype=bool)
    if len(x) &gt; 0:
        keep[0] = keep[-1] = True
        keep[1:-1] = (y[1:-1] != y[:-2]) | (y[1:-1] != y[2:])
    return x[keep], y[keep]


Notes on this code:


This returns NumPy arrays (not Python lists), so you'll need to revise your test cases to use numpy.testing.assert_array_equal instead of unittest.TestCase.assertEqual.
If you pass it Python lists, then much of the runtime will be in the numpy.asarray call (converting the input to NumPy arrays) and not in the compression code. So for a fair test I think it makes sense to update test_time_self so that it calls numpy.arange instead of range. 

With this change, I find that the revised code is about 30 times faster than the original code.


A couple of other review points:


There's no docstring for compress_2D_signal. It's hard to use and maintain code when there's no documentation.
The test case code is very repetitive — it would be simpler to loop over a list of cases, like this:

from numpy.testing import assert_array_equal

class Test2DSignal(TestCase):
    _CASES = [
        # x, y, x1, y1
        ([1, 2, 3, 4], [0, 1, 2, 3],
         [1, 2, 3, 4], [0, 1, 2, 3]),
        ([1, 2, 3, 4, 5], [0, 2, 2, 2, 0],
         [1, 2, 4, 5], [0, 2, 2, 0]),
        ([1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 2, 2, 2, 0, 0, 1, 1, 1], 
         [1, 2, 4, 5, 6, 7, 9], [0, 2, 2, 0, 0, 1, 1]),
    ]

    def test_2D_signal(self):
        for x, y, x1_expected, y1_expected in self._CASES:
            x1_found, y1_found = compress_2D_signal(x, y)
            assert_array_equal(x1_expected, x1_found)
            assert_array_equal(y1_expected, y1_found)


This makes it easier to add new cases. In particular, I would add tests for edge cases such as empty and single-element inputs, like this:

    _CASES = [
        # x, y, x1, y1
        ([], [], [], []),
        ([1], [1], [1], [1]),
        ([1, 2], [1, 1], [1, 2], [1, 1]),
        ([1, 2, 3], [1, 1, 1], [1, 3], [1, 1]),
        # etc.