np.where перебирает несколько опций в условных выражениях - длина должна соответствовать ошибке - PullRequest
0 голосов
/ 15 января 2020

Я бы хотел, чтобы код перебирал опции в моих условных выражениях, чтобы мне не приходилось копировать и вставлять один и тот же код снова и снова только с условным изменением.

Это мой код Чак:

for row in range(0, len(all_data)):
    all_data['Zone'] = np.where((all_data['Freq'] == [60, 132]) &
                                (all_data['YMD'] == ['2019-11-05 00:00:00', '2019-11-18 00:00:00']) &
                                (all_data['observation'] == ['2', '2']), ['u', 'u'],
                                [all_data['Zone'], all_data['Zone']])

Однако я получаю следующую ошибку и трассировку:

Трассировка (последний вызов последним): Файл "C: \ ProgramData \ Anaconda3 \ lib \ site-packages \ IPython \ core \ interactiveshell.py ", строка 3319, в run_code exe c (code_obj, файл self.user_global_ns, self.user_ns)" ", строка 4, в (all_data ['YMD'] = = ['2019-11-05 00:00:00', '2019-11-18 00:00:00']) & Файл "C: \ ProgramData \ Anaconda3 \ lib \ site-packages \ pandas \ core \ ops__init __. py ", строка 1179, в обёртке , строка 630, в dispatch_to_index_op result = op (left_idx, right) Файл "C: \ ProgramData \ Anaconda3 \ lib \ site-packages \ pandas \ core \ indexes \ datet imelike.py ", строка 132, в оболочке result = op (self._data, Maybe_unwrap_index (other)) Файл" C: \ ProgramData \ Anaconda3 \ lib \ site-packages \ pandas \ core \ arrays \ datetimes.py " строка 182, в повышении оболочки ValueError («Длина должна совпадать») ValueError: Длина должна совпадать

Похоже, ошибка «ValueError: длина должна совпадать». Я попытался исправить эту ошибку, продублировав значение замены "u" и местоположение замены "all_data ['Zone']", но это, очевидно, не решило проблему. Я не совсем уверен, где я ошибся или как решить проблему. Если у кого-то есть альтернативное решение использования np.where, которое достигает той же цели, я открыт для этого решения.

EDIT1 - Добавлены данные примера

Freq    YMD     Zone    observation

60  10/21/2019     A    1

60  10/21/2019     A    2

60  11/5/2019      A    1

60  11/5/2019      A    2

60  11/18/2019     0    1

60  11/18/2019     0    2

132 10/10/2019     A    2

132 10/21/2019     A    1

132 10/21/2019     A    2

132 11/5/2019      A    1

132 11/5/2019      A    2

132 11/18/2019     A    1

132 11/18/2019     A    2

170 8/31/2019      A    1

170 8/31/2019      N    2

170 9/1/2019       N    1

EDIT2 - добавлен пример ожидаемого вывода

Freq    YMD     Zone    observation

60  10/21/2019     A    1

60  10/21/2019     A    2

60  11/5/2019      A    1

60  11/5/2019      u    2

60  11/18/2019     0    1

60  11/18/2019     0    2

132 10/10/2019     A    2

132 10/21/2019     A    1

132 10/21/2019     A    2

132 11/5/2019      A    1

132 11/5/2019      A    2

132 11/18/2019     A    1

132 11/18/2019     u    2

170 8/31/2019      A    1

170 8/31/2019      N    2

170 9/1/2019       N    1

Edit3 - неуклюжий код, который соответствует цели Этот код делает то, что мне нужно, но я не хочу, чтобы копируйте и вставляйте кодовые фрагменты снова и снова для каждой новой комбинации "freq" и "YMD". Я хотел бы просто иметь список в условных выражениях для перебора. то есть, если у меня есть 6 различных комбинаций "Freq" и "YMD", мне нужно будет вставить блок кода 6 раз и просто изменить условия. Это может сделать код очень длинным и неряшливым с достаточным количеством условных комбинаций.

all_data['Zone'] = np.where((all_data['Freq'] == 60) &
                            (all_data['YMD'] == '2019-11-05 00:00:00') &
                            (all_data['observation'] == '2'), 'u',
                            all_data['Zone'])
all_data['Zone'] = np.where((all_data['Freq'] == 132) &
                            (all_data['YMD'] == '2019-11-18 00:00:00') &
                            (all_data['observation'] == '2'), 'u',
                            all_data['Zone'])

Ответы [ 2 ]

1 голос
/ 15 января 2020

Я думаю, что проблема заключается в тестировании Series (столбец данных) с несколькими значениями одновременно, как в (all_data['Freq'] == [60, 132])

Создайте простую серию:

In [190]: s = pd.Series(['a','b','c','b','d'])                                                   
In [191]: s                                                                                      
Out[191]: 
0    a
1    b
2    c
3    b
4    d
dtype: object

test это против одного значения:

In [192]: s=='a'                                                                                 
Out[192]: 
0     True
1    False
2    False
3    False
4    False
dtype: bool

Это хорошая логическая серия, которая может быть объединена с другим тестом. Вы используете & для объединения тестов в разных столбцах, но из примера «неуклюжий» я понимаю, что вам нужна комбинация | или «для одного столбца:

In [193]: (s=='a')|(s=='b')                                                                      
Out[193]: 
0     True
1     True
2    False
3     True
4    False
dtype: bool

У вас проблемы при попытке сделать это 'или' проверить таким образом:

In [194]: s==['a','b']                                                                           
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-194-a889b3de7e64> in <module>
----> 1 s==['a','b']

/usr/local/lib/python3.6/dist-packages/pandas/core/ops/__init__.py in wrapper(self, other, axis)
   1205             # as it will broadcast
   1206             if other.ndim != 0 and len(self) != len(other):
-> 1207                 raise ValueError("Lengths must match to compare")
   1208 
   1209             res_values = na_op(self.values, np.asarray(other))

ValueError: Lengths must match to compare

5 значений s не соответствуют 2 на RHS.

Если вы выполните тест строка за строкой запускается, хотя в результате есть «и» logi c, а не «или». Строка должна соответствовать обеим строкам, чего она не может:

In [195]: for row in s: 
     ...:     print(row==['a','b']) 
     ...:                                                                                        
False
False
False
False
False

numpy и pandas реализуют broadcasting, что позволяет нам выполнять более сложные тесты. Используя values, массив numpy, полученный из Series, который я могу сделать:

In [197]: s.values[:,None]==['a','b']                                                            
Out[197]: 
array([[ True, False],
       [False,  True],
       [False, False],
       [False,  True],
       [False, False]])
In [198]: _.any(axis=1)                                                                          
Out[198]: array([ True,  True, False,  True, False])

такая же последовательность True / False, как в Out[193]

Альтернатива копии и вставить будет параметризованное сравнение:

for a,b,c in [(60,'2019...','2'),(52,'2020...','3')]:
    all_data['Zone'] = np.where((all_data['Freq'] == a) &
                            (all_data['YMD'] == b) &
                            (all_data['observation'] == c), 'u',
                            all_data['Zone'])
0 голосов
/ 15 января 2020

np.where пытается сопоставить точные значения, это ваше намерение? Можете ли вы опубликовать пример данных, я предполагаю, что один из элементов кадра данных не имеет одинаковую длину (например, вероятно, дата должна быть между двумя перечисленными моментами? Но вместо этого проверяются по списку с 2 элементами дат).

(all_data['YMD'] > '2019-11-05 00:00:00' & all_data['YMD'] < '2019-11-18 00:00:00']) &
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...