TypeError: Singleton array array(True) cannot be considered a valid collection

Question:

I want split the dataset that I have into test/train while also ensuring that the distribution of classified labels are same in both test/train. To do this I am using the stratify option but it is throwing an error as follows:

X_full_train, X_full_test, Y_full_train, Y_full_test = train_test_split(X_values_full, Y_values, test_size = 0.33, random_state = 42, stratify = True)

Error message:

TypeError                                 Traceback (most recent call last)
 in 
     19 
     20 
---> 21 X_full_train, X_full_test, Y_full_train, Y_full_test = train_test_split(X_values_full, Y_values, test_size = 0.33, random_state = 42, stratify = True)
     22 
     23 

~/anaconda3/lib/python3.8/site-packages/sklearn/model_selection/_split.py in train_test_split(*arrays, **options)
   2150                      random_state=random_state)
   2151 
-> 2152         train, test = next(cv.split(X=arrays[0], y=stratify))
   2153 
   2154     return list(chain.from_iterable((_safe_indexing(a, train),

~/anaconda3/lib/python3.8/site-packages/sklearn/model_selection/_split.py in split(self, X, y, groups)
   1744         to an integer.
   1745         """
-> 1746         y = check_array(y, ensure_2d=False, dtype=None)
   1747         return super().split(X, y, groups)
   1748 

~/anaconda3/lib/python3.8/site-packages/sklearn/utils/validation.py in inner_f(*args, **kwargs)
     71                           FutureWarning)
     72         kwargs.update({k: arg for k, arg in zip(sig.parameters, args)})
---> 73         return f(**kwargs)
     74     return inner_f
     75 

~/anaconda3/lib/python3.8/site-packages/sklearn/utils/validation.py in check_array(array, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, ensure_min_samples, ensure_min_features, estimator)
    647 
    648     if ensure_min_samples > 0:
--> 649         n_samples = _num_samples(array)
    650         if n_samples < ensure_min_samples:
    651             raise ValueError("Found array with %d sample(s) (shape=%s) while a"

~/anaconda3/lib/python3.8/site-packages/sklearn/utils/validation.py in _num_samples(x)
    194     if hasattr(x, 'shape') and x.shape is not None:
    195         if len(x.shape) == 0:
--> 196             raise TypeError("Singleton array %r cannot be considered"
    197                             " a valid collection." % x)
    198         # Check that shape is returning an integer or default to len

TypeError: Singleton array array(True) cannot be considered a valid collection.

When I try to do this without the stratify option it does not give me an error. I thought that this was because my Y labels don’t have the minimum number of samples required to distribute the labels evenly between test/train but:

pp.pprint(Counter(Y_values))

gives:

Counter({13: 1084,
         1: 459,
         7: 364,
         8: 310,
         38: 295,
         15: 202,
         4: 170,
         37: 105,
         3: 98,
         0: 85,
         24: 79,
         20: 78,
         35: 76,
         2: 75,
         12: 74,
         39: 72,
         22: 71,
         9: 63,
         26: 59,
         11: 55,
         18: 55,
         32: 53,
         19: 53,
         33: 53,
         5: 52,
         30: 42,
         29: 42,
         25: 41,
         10: 39,
         23: 38,
         21: 38,
         6: 38,
         27: 37,
         14: 36,
         36: 36,
         34: 34,
         28: 33,
         17: 31,
         31: 30,
         16: 30})
Asked By: specinthedark

||

Answers:

Per the sklearn documentation:

stratifyarray-like, default=None If not None, data is split in a
stratified fashion, using this as the class labels.

Thus, it does not accept a boolean value like True or False, but the class labels themselves.

So, you need to change:

X_full_train, X_full_test, Y_full_train, Y_full_test = train_test_split(X_values_full, Y_values, test_size = 0.33, random_state = 42, stratify = True)

to:

X_full_train, X_full_test, Y_full_train, Y_full_test = train_test_split(X_values_full, Y_values, test_size = 0.33, random_state = 42, stratify = Y_values)
Answered By: artemis
  • Error Clarification:

I think this error arises because your label is continuous, not categorical one. And by nature, stratify cannot work with continuous column that have many unique values.
A simple solution is to make a new column that encodes your Y_label to categorical one ex Y_label_cat:
Y_values_cat = pd.qcut(Y_values,[0, .25, .5, .75, 1.],labels = ["1st","2nd","3rd","4th"])
and then you can pass the parameter like this: stratify = Y_label_cat

  • Final Code:

X_full_train, X_full_test, Y_full_train, Y_full_test = train_test_split(X_values_full, Y_values, test_size = 0.33, random_state = 42, stratify = Y_label_cat)

Answered By: Omar Allam