Repository: blue-yonder/tsfresh

Issue:
Off-by-one error in longest strike features
The two features `longest_strike_below_mean` and `longest_strike_above_mean` are implemented in a "less-than" and "greater-than" fashion, which yields incorrect results.

Here is a MWE where µ = 3 and the longest strike below and above is 2 - `tsfresh` yields 3.

```
assert fc.longest_strike_below_mean([1, 2, 3, 4, 5]) == 2
assert fc.longest_strike_above_mean([1, 2, 3, 4, 5]) == 2
```


Discussion:
coveralls: 
[![Coverage Status](https://coveralls.io/builds/26432159/badge)](https://coveralls.io/builds/26432159)

Coverage remained the same at ?% when pulling **973d495dd6584d682a778cfb46cc02cea96b6436 on blu3r4y:fix-longest-strike** into **c3d35c42c799d1f36a1aca1d90ec0ab6450ce264 on blue-yonder:master**.


Patch:
diff --git a/tsfresh/feature_extraction/feature_calculators.py b/tsfresh/feature_extraction/feature_calculators.py
index b5c8823..3df61b6 100644
--- a/tsfresh/feature_extraction/feature_calculators.py
+++ b/tsfresh/feature_extraction/feature_calculators.py
@@ -691,7 +691,7 @@ def longest_strike_below_mean(x):
     """
     if not isinstance(x, (np.ndarray, pd.Series)):
         x = np.asarray(x)
-    return np.max(_get_length_sequences_where(x <= np.mean(x))) if x.size > 0 else 0
+    return np.max(_get_length_sequences_where(x < np.mean(x))) if x.size > 0 else 0
 
 
 @set_property("fctype", "simple")
@@ -706,7 +706,7 @@ def longest_strike_above_mean(x):
     """
     if not isinstance(x, (np.ndarray, pd.Series)):
         x = np.asarray(x)
-    return np.max(_get_length_sequences_where(x >= np.mean(x))) if x.size > 0 else 0
+    return np.max(_get_length_sequences_where(x > np.mean(x))) if x.size > 0 else 0
 
 
 @set_property("fctype", "simple")


Test patch:
diff --git a/tests/units/feature_extraction/test_feature_calculations.py b/tests/units/feature_extraction/test_feature_calculations.py
index 129e9c3..942e1a1 100644
--- a/tests/units/feature_extraction/test_feature_calculations.py
+++ b/tests/units/feature_extraction/test_feature_calculations.py
@@ -372,11 +372,15 @@ class FeatureCalculationTestCase(TestCase):
 
     def test_longest_strike_below_mean(self):
         self.assertEqualOnAllArrayTypes(longest_strike_below_mean, [1, 2, 1, 1, 1, 2, 2, 2], 3)
+        self.assertEqualOnAllArrayTypes(longest_strike_below_mean, [1, 2, 3, 4, 5, 6], 3)
+        self.assertEqualOnAllArrayTypes(longest_strike_below_mean, [1, 2, 3, 4, 5], 2)
         self.assertEqualOnAllArrayTypes(longest_strike_below_mean, [1, 2, 1], 1)
         self.assertEqualOnAllArrayTypes(longest_strike_below_mean, [], 0)
 
     def test_longest_strike_above_mean(self):
         self.assertEqualOnAllArrayTypes(longest_strike_above_mean, [1, 2, 1, 2, 1, 2, 2, 1], 2)
+        self.assertEqualOnAllArrayTypes(longest_strike_above_mean, [1, 2, 3, 4, 5, 6], 3)
+        self.assertEqualOnAllArrayTypes(longest_strike_above_mean, [1, 2, 3, 4, 5], 2)
         self.assertEqualOnAllArrayTypes(longest_strike_above_mean, [1, 2, 1], 1)
         self.assertEqualOnAllArrayTypes(longest_strike_above_mean, [], 0)