Сокращение потребления памяти pandas DataFrame за счет использования масштабированных данных для каждого столбца? - PullRequest
0 голосов
/ 01 апреля 2020

Я хотел бы уменьшить потребление памяти при управлении некоторыми pandas DataFrame. Мне известна хитрость, например, для переключения с float64 на flot32, и это интересно.

К go еще дальше, и зная, что мои числовые значения c имеют фактически "маленькие" абсолютные минимальные и максимальные значения Мне было интересно, нельзя ли попросить pandas использовать масштабный коэффициент для данного столбца?

Лучший пример может быть с процентами.

С процентами, вы знаете, min равно 0, а max равно 1. Эти минимальные и максимальные значения могут быть сохранены в качестве атрибутов столбца.

Затем я могу использовать, например, int16, а значения столбцов будут сохраняться как масштабированные значения между [-128; 127]. Затем, при использовании, они будут уменьшены до своего «исходного значения» (с некоторым округлением) с использованием значений min и max, которые были сохранены как атрибут столбца.

Возможен ли такой подход для управления pandas DataFrames?

Спасибо за вашу помощь и отзывы! Bests,

1 Ответ

2 голосов
/ 01 апреля 2020

Я использую эту полезную вспомогательную функцию. Но, конечно, могут быть использованы лучшие решения.

def reduce_mem_usage(data_frame):
    start_mem_usg = data_frame.memory_usage(deep=True).sum() / 1024 ** 2
    print("Memory usage of the dataframe is : {:03.2f} {}".format(start_mem_usg, " MB"))
    for col in data_frame.columns:
        if data_frame[col].dtype not in [object, "datetime64", "datetime64[ns]"]:  # Exclude strings

            print("******************************")
            print("Column: ", col)
            print("dtype before: ", data_frame[col].dtype)
            is_int = False
            try:
                mx = data_frame[col].max()
            except Exception:
                continue
            mn = data_frame[col].min()
            try:
                as_int = data_frame[col].fillna(0).astype(numpy.int64)
                result = (data_frame[col] - as_int)
                result = result.sum()
                if result > -0.01 and result < 0.01:
                    is_int = True
            except:
                continue

            try:

                if is_int:
                    if mn >= 0:
                        if mx < 255:
                            data_frame[col] = data_frame[col].astype(numpy.uint8)
                        elif mx < 65535:
                            data_frame[col] = data_frame[col].astype(numpy.uint16)
                        elif mx < 4294967295:
                            data_frame[col] = data_frame[col].astype(numpy.uint32)
                        else:
                            data_frame[col] = data_frame[col].astype(numpy.uint64)
                    else:
                        if mn > numpy.iinfo(numpy.int8).min and mx < numpy.iinfo(numpy.int8).max:
                            data_frame[col] = data_frame[col].astype(numpy.int8)
                        elif mn > numpy.iinfo(numpy.int16).min and mx < numpy.iinfo(numpy.int16).max:
                            data_frame[col] = data_frame[col].astype(numpy.int16)
                        elif mn > numpy.iinfo(numpy.int32).min and mx < numpy.iinfo(numpy.int32).max:
                            data_frame[col] = data_frame[col].astype(numpy.int32)
                        elif mn > numpy.iinfo(numpy.int64).min and mx < numpy.iinfo(numpy.int64).max:
                            data_frame[col] = data_frame[col].astype(numpy.int64)

                            # Make float datatypes 32 bit
                else:
                    data_frame[col] = data_frame[col].astype(numpy.float32)
                print("dtype after: ", data_frame[col].dtype)
                print("******************************")
            except ValueError:
                continue
    print("___MEMORY USAGE AFTER COMPLETION:___")
    mem_usg = data_frame.memory_usage(deep=True).sum() / 1024 ** 2
    print("Memory usage is: {:03.2f} {}".format(mem_usg, " MB"))
    print("This is ", 100 * mem_usg / start_mem_usg, "% of the initial size")
    return data_frame
...