Когда я создаю DataFrame из поплавков и выполняю any(df.isna())
, он всегда возвращает True, независимо от содержимого массива. Я ожидаю, что это даст тот же результат, что и df.isna().any().any()
. Что мне не хватает?
import pandas as pd
import numpy as np
import sys
print(f'Pandas version {pd.__version__}')
print(f'Numpy version {np.__version__}')
print(f'Python version: {sys.version}')
df = pd.DataFrame(np.random.random((5, 3)))
print(f'The DataFrame:\n{df}')
print(f'Result of any(df.isna()): {any(df.isna())}')
print(f'Result of df.isna().any().any(): {df.isna().any().any()}')
Выходы:
Pandas version 1.1.4
Numpy version 1.19.4
Python version: 3.7.8 | packaged by conda-forge | (default, Nov 27 2020, 18:48:03) [MSC v.1916 64 bit (AMD64)]
The DataFrame:
0 1 2
0 0.972085 0.418991 0.736300
1 0.603018 0.280435 0.981732
2 0.376201 0.343994 0.026125
3 0.002652 0.683785 0.729332
4 0.759530 0.792976 0.436991
Result of any(df.isna()): True
Result of df.isna().any().any(): False
Причина в том, что df.isna()
— это фрейм данных. И когда вы перебираете фрейм данных, вы фактически перебираете имена столбцов:
for x in df.isna():
print(x)
С другой стороны, функция Python any
выглядит примерно так:
def anyPython(iterable):
for x in iterable:
if bool(x): return True
return False
А что происходит, когда вы делаете bool('some string')
?
any
и DataFrame
объектыПричина, по которой вы получаете этот вывод, заключается в том, что any
возвращает True
, если какой-либо элемент итерации оценивается как True
, иначе False
, а DataFrame
, рассматриваемый как итерация, предоставит имена своих столбцов. Любой непустой str
оценивается как True
, а любой ненулевой int
будет оцениваться как True
- как в вашем примере - поэтому any
действует так, как и ожидалось.
Чтобы получить ожидаемый результат (True
, если какой-либо элемент итерации оценивается как True
, иначе False
) на основе значений, содержащихся в df
, вы можете использовать любой из следующих примеров.
df.isna().values.any() # Example 1
any(df.isna().values.flatten()) # Example 2
Использование isdf.isna().values
возвращает numpy.ndarray
, содержащее значения df.na()
, которые затем используются в одной из двух различных функций any
.
В первом приведенном примере используется numpy.any вместо встроенной функции any. numpy.any
оценивает все элементы всех измерений заданного ndarray
, если axis
kwarg равен None
(по умолчанию).
Причина, по которой numpy.ndarray.flatten используется во втором примере, заключается в том, что df.values
вернет многомерное ndarray
, а поскольку any(args)
выполняет поэлементные проверки переданного итерируемого объекта, вы получите следующую ошибку во время выполнения.
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
flatten
делает именно то, на что это похоже — сопоставляет значения многомерного ndarray
с одномерным, которые можно соответствующим образом повторять и оценивать с помощью any(your_flat_array)
.
Я счел уместным объяснить здесь разницу между этими двумя подходами, хотя почему вы решили выбрать второй, для меня загадка.
Я считаю, что причина в том, что функция any() не ожидает df, вы можете использовать список, кортеж или dict. Например, попробуйте сложить элементы df и превратить их в ist. Тогда вы получите any(df.isna().stack().tolist()) a False .