Создать пустой фреймворк в Pandas с указанием типов столбцов

Я пытаюсь создать пустой фрейм данных с индексом и указать типы столбцов. Способ, которым я это делаю, следующий:

df = pd.DataFrame(index=['pbp'],columns=['contract',
                                         'state_and_county_code',
                                         'state',
                                         'county',
                                         'starting_membership',
                                         'starting_raw_raf',
                                         'enrollment_trend',
                                         'projected_membership',
                                         'projected_raf'],
                                dtype=['str', 'str', 'str', 'str', 'int', 'float', 'float', 'int', 'float'])

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

TypeError: data type not understood

Что это значит?

Ответ 1

Это действительно пахнет ошибкой.

Здесь другое (более простое) решение.

import pandas as pd
import numpy as np

def df_empty(columns, dtypes, index=None):
    assert len(columns)==len(dtypes)
    df = pd.DataFrame(index=index)
    for c,d in zip(columns, dtypes):
        df[c] = pd.Series(dtype=d)
    return df

df = df_empty(['a', 'b'], dtypes=[np.int64, np.int64])
print(list(df.dtypes)) # int64, int64

Ответ 2

Просто замечание.

Вы можете обойти Type Error с помощью np.dtype:

pd.DataFrame(index = ['pbp'], columns = ['a','b'], dtype = np.dtype([('str','float')]))

но вместо этого вы получаете:

NotImplementedError: compound dtypes are not implementedin the DataFrame constructor

Ответ 3

Я нашел этот вопрос, столкнувшись с тем же вопросом. Я предпочитаю следующее решение (Python 3) для создания пустого DataFrame без индекса.

import numpy as np
import pandas as pd

def make_empty_typed_df(dtype):
    tdict = np.typeDict
    types = tuple(tdict.get(t, t) for (_, t, *__) in dtype)
    if any(t == np.void for t in types):
        raise NotImplementedError('Not Implemented for columns of type "void"')
    return pd.DataFrame.from_records(np.array([tuple(t() for t in types)], dtype=dtype)).iloc[:0, :]

Тестирование этого...

from itertools import chain

dtype = [('col%d' % i, t) for i, t in enumerate(chain(np.typeDict, set(np.typeDict.values())))]
dtype = [(c, t) for (c, t) in dtype if (np.typeDict.get(t, t) != np.void) and not isinstance(t, int)]

print(make_empty_typed_df(dtype))

Из:

Empty DataFrame

Columns: [col0, col6, col16, col23, col24, col25, col26, col27, col29, col30, col31, col32, col33, col34, col35, col36, col37, col38, col39, col40, col41, col42, col43, col44, col45, col46, col47, col48, col49, col50, col51, col52, col53, col54, col55, col56, col57, col58, col60, col61, col62, col63, col64, col65, col66, col67, col68, col69, col70, col71, col72, col73, col74, col75, col76, col77, col78, col79, col80, col81, col82, col83, col84, col85, col86, col87, col88, col89, col90, col91, col92, col93, col95, col96, col97, col98, col99, col100, col101, col102, col103, col104, col105, col106, col107, col108, col109, col110, col111, col112, col113, col114, col115, col117, col119, col120, col121, col122, col123, col124, ...]
Index: []

[0 rows x 146 columns]

И типы данных...

print(make_empty_typed_df(dtype).dtypes)

Из:

col0      timedelta64[ns]
col6               uint16
col16              uint64
col23                int8
col24     timedelta64[ns]
col25                bool
col26           complex64
col27               int64
col29             float64
col30                int8
col31             float16
col32              uint64
col33               uint8
col34              object
col35          complex128
col36               int64
col37               int16
col38               int32
col39               int32
col40             float16
col41              object
col42              uint64
col43              object
col44               int16
col45              object
col46               int64
col47               int16
col48              uint32
col49              object
col50              uint64
               ...       
col144              int32
col145               bool
col146            float64
col147     datetime64[ns]
col148             object
col149             object
col150         complex128
col151    timedelta64[ns]
col152              int32
col153              uint8
col154            float64
col156              int64
col157             uint32
col158             object
col159               int8
col160              int32
col161             uint64
col162              int16
col163             uint32
col164             object
col165     datetime64[ns]
col166            float32
col167               bool
col168            float64
col169         complex128
col170            float16
col171             object
col172             uint16
col173          complex64
col174         complex128
dtype: object

Добавление индекса становится сложным, потому что для большинства типов данных нет истинного отсутствующего значения, поэтому они получают отливку от какого-либо другого типа с собственным отсутствующим значением (например, int передаются в float или object s), но если у вас есть полные данные о типах, которые вы указали, вы всегда можете вставлять строки по мере необходимости, и ваши типы будут соблюдаться. Это можно сделать с помощью:

df.loc[index, :] = new_row

Опять же, как отметил @Hun, это НЕ, как предполагается Pandas.

Ответ 4

pandas не предлагает чистый целочисленный столбец. Вы можете использовать столбец float и преобразовать этот столбец в целое число по мере необходимости или рассматривать его как объект. То, что вы пытаетесь реализовать, не означает, что предполагается использовать pandas. Но если вы ДЕЙСТВИТЕЛЬНО ДЕЙСТВИТЕЛЬНО хотите этого, вы можете обойти сообщение TypeError, выполнив это.

df1 =  pd.DataFrame(index=['pbp'], columns=['str1','str2','str2'], dtype=str)
df2 =  pd.DataFrame(index=['pbp'], columns=['int1','int2'], dtype=int)
df3 =  pd.DataFrame(index=['pbp'], columns=['flt1','flt2'], dtype=float)
df = pd.concat([df1, df2, df3], axis=1)

    str1 str2 str2 int1 int2  flt1  flt2
pbp  NaN  NaN  NaN  NaN  NaN   NaN   NaN

Вы можете упорядочить порядок col, как вам нравится. Но опять же, это не способ использования pandas.

 df.dtypes
str1     object
str2     object
str2     object
int1     object
int2     object
flt1    float64
flt2    float64
dtype: object

Обратите внимание, что int рассматривается как объект.

Ответ 5

Вы можете сделать это, передав словарь в конструктор DataFrame:

df = pd.DataFrame(index=['pbp'],
                  data={'contract' : np.full(1, "", dtype=str),
                        'starting_membership' : np.full(1, np.nan, dtype=float),
                        'projected_membership' : np.full(1, np.nan, dtype=int)
                       }
                 )

Это правильно даст вам фреймворк данных, который выглядит следующим образом:

     contract  projected_membership   starting_membership
pbp     ""             NaN           -9223372036854775808

С dtypes:

contract                 object
projected_membership    float64
starting_membership       int64

Тем не менее, есть две вещи, которые следует отметить:

1) str не является фактически типом, который может обрабатывать столбец DataFrame; вместо этого он возвращается к общему случаю object. Он будет работать нормально.

2) Почему вы не видите NaN под starting_membership? Ну, NaN определяется только для поплавков; для целых чисел нет значения "Нет", поэтому он отличает np.NaN от целого. Если вы хотите другое значение по умолчанию, вы можете изменить это в вызове np.full.

Ответ 6

Вы можете сделать это так

import numpy
import pandas

dtypes = numpy.dtype([
          ('a', str),
          ('b', int),
          ('c', float),
          ('d', numpy.datetime64),
          ])
data = numpy.empty(0, dtype=dtypes)
df = pandas.DataFrame(data)

Ответ 7

Это старый вопрос, но я не вижу твердого ответа (хотя @eric_g был очень близок).

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

Поэтому в вашем примере набора данных это выглядит следующим образом:

df = pd.DataFrame(,columns=[{'contract':'',
                              'state_and_county_code':'',
                              'state':'',
                              'county':'',
                              'starting_membership':int(),
                              'starting_raw_raf':float(),
                              'enrollment_trend':float(),
                              'projected_membership':int(),
                              'projected_raf':float(),
                              'pbp':int() #just guessing on this data type
                                      }]).set_index=("pbp")

Ответ 8

Я нашел самый простой обходной путь для меня, это просто объединить список пустых рядов для каждого отдельного столбца:

import pandas as pd

columns = ['contract',
           'state_and_county_code',
           'state',
           'county',
           'starting_membership',
           'starting_raw_raf',
           'enrollment_trend',
           'projected_membership',
           'projected_raf']
dtype = ['str', 'str', 'str', 'str', 'int', 'float', 'float', 'int', 'float']
df = pd.concat([pd.Series(name=col, dtype=dt) for col, dt in zip(columns, dtype)], axis=1)
df.info()
# <class 'pandas.core.frame.DataFrame'>
# Index: 0 entries
# Data columns (total 9 columns):
# contract                 0 non-null object
# state_and_county_code    0 non-null object
# state                    0 non-null object
# county                   0 non-null object
# starting_membership      0 non-null int32
# starting_raw_raf         0 non-null float64
# enrollment_trend         0 non-null float64
# projected_membership     0 non-null int32
# projected_raf            0 non-null float64
# dtypes: float64(3), int32(2), object(4)
# memory usage: 0.0+ bytes