Как определить, является ли фреймворк смешанного типа?

Я хочу присвоить значения диагонали кадра данных. Самый быстрый способ, который я могу придумать, - использовать numpy np.diag_indices и выполнить назначение среза в массиве values. Тем не менее, массив значений является только представлением и готов принять назначение, когда фреймворк данных имеет один dtype

Рассмотрим кадры данных d1 и d2

d1 = pd.DataFrame(np.ones((3, 3), dtype=int), columns=['A', 'B', 'C'])
d2 = pd.DataFrame(dict(A=[1, 1, 1], B=[1., 1., 1.], C=[1, 1, 1]))

d1

   A  B  C
0  0  1  1
1  1  0  1
2  1  1  0

d2

   A    B  C
0  1  1.0  1
1  1  1.0  1
2  1  1.0  1

Тогда получим наши индексы

i, j = np.diag_indices(3)

d1 имеет один dtype и, следовательно, работает

d1.values[i, j] = 0
d1

   A  B  C
0  0  1  1
1  1  0  1
2  1  1  0

Но не на d2

d2.values[i, j] = 0
d2

   A    B  C
0  1  1.0  1
1  1  1.0  1
2  1  1.0  1

Мне нужно написать функцию и сделать ее неудачной, если df имеет смешанный dtype. Как я могу проверить, что это такое? Должен ли я доверять этому, если это так, это задание с помощью представления всегда будет работать?

Ответ 1

Вы можете использовать внутренний метод _is_mixed_type

In [3600]: d2._is_mixed_type
Out[3600]: True

In [3601]: d1._is_mixed_type
Out[3601]: False

Или, проверьте уникальный dtypes

In [3602]: d1.dtypes.nunique()>1
Out[3602]: False

In [3603]: d2.dtypes.nunique()>1
Out[3603]: True

Немного де-тура, is_mixed_type проверяет, как blocks консолидируются.

In [3618]: len(d1.blocks)>1
Out[3618]: False

In [3619]: len(d2.blocks)>1
Out[3619]: True

In [3620]: d1.blocks    # same as d1.as_blocks()
Out[3620]:
{'int32':    A  B  C
 0  0  1  1
 1  1  0  1
 2  1  1  0}

In [3621]: d2.blocks
Out[3621]:
{'float64':      B
 0  1.0
 1  1.0
 2  1.0, 'int64':    A  C
 0  1  1
 1  1  1
 2  1  1}

Ответ 2

def check_type(df):
  return len(set(df.dtypes)) == 1

или

 def check_type(df):
   return df.dtypes.nunique() == 1

Ответ 3

Вы можете проверить DataFrame.dtypes, чтобы проверить типы столбцов. Например:

>>> d1.dtypes
A    int64
B    int64
C    int64
dtype: object
>>> d2.dtypes
A      int64
B    float64
C      int64
dtype: object

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

np.all(d1.dtypes == d1.dtypes[0])

Для ваших фреймов данных:

>>> np.all(d1.dtypes == d1.dtypes[0])
True
>>> np.all(d2.dtypes == d2.dtypes[0])
False

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

def all_columns_same_type(df):
    dtypes = df.dtypes
    return not dtypes.empty and np.all(dtypes == dtypes[0])