簡體   English   中英

Pandas memory 使用和 memory 分配

[英]Pandas memory usage and memory allocation

我正在嘗試使用 pandas 分析一個大的 csv (csv 是 ~3GB 和 ~600 萬行)(我的計算機有 32GB 的 RAM 內存,我無法將其加載到大塊中)。 我可以毫無問題地閱讀 csv,但是一旦我開始清理文件,整個腳本就會崩潰。 Monitoring the memory usage of my computer I found that just to have the csv stored in a pandas DataFrame 50% of my RAM (18GB) is used. 當我開始修改 DataFrame 時,memory 的使用率飆升至 100% 並導致我的腳本崩潰。 使用 DataFrame 方法memory_usage(deep=True)我發現我的 DataFrame 對於 pandas 是 3GB。 但是 pandas 怎么可能告訴我我的變量是 3GB 而我的 memory 使用量是 18GB(可能是 13GB,因為操作系統使用了 %GB)?

這是一個例子:

raw = pd.read_csv("db.csv", sep="\t", on_bad_lines="skip", dtypes="object")

remove_invalid_ateco = lambda df_: df_[df_.ateco.str.contains("\.")]
months_diff = lambda a, b: 12 * (a.year - b.dt.year) + (a.month - b.dt.month)
raw.query(
            "~piva.isnull() and"
            "~code.isnull() and "
            "provincia_cd.str.len() == 2"
        )
        .pipe(remove_invalid_ateco)
        .assign(
            # Float
            roe=lambda df_: df_.roe.str.replace(",", "."),
            roi=lambda df_: df_.roi.str.replace(",", "."),
            ros=lambda df_: df_.ros.str.replace(",", "."),
            longitudine_dd=lambda df_: df_.longitudine_dd.str.replace(",", "."),
            latitudine_dd=lambda df_: df_.latitudine_dd.str.replace(",", "."),
            sfin=lambda df_: df_.sfin.str.replace(",", "."),
            cap_del=lambda df_: df_.cap_del.str.replace(
                ",", "."
            ),
            cap_sott=lambda df_: df_.cap_sott.str.replace(
                ",", "."
            ),
            cap_vers=lambda df_: df_.cap_vers.str.replace(",", "."),
            eq_ec_1=lambda df_: df_.eq_ec_1.str.replace(",", "."),
            eq_eff_1=lambda df_: df_.eq_eff_1.str.replace(",", "."),
            eq_fin_1=lambda df_: df_.eq_fin_1.str.replace(",", "."),
            eq_liq_1=lambda df_: df_.eq_liq_1.str.replace(",", "."),
            eq_pat_1=lambda df_: df_.eq_pat_1.str.replace(",", "."),
            # Date
            date_iscr=lambda df_: pd.to_datetime(
                df_.date_iscr, errors="coerce"
            ),
            date_init=lambda df_: pd.to_datetime(
                df_.date_init, errors="coerce"
            ),
            delta=lambda df_: months_diff(
                datetime.today(), pd.to_datetime(df_.date_init, errors="coerce")
            ),
        )

我將使用我的庫 - convtools ,有Table助手(文檔| github )允許將表格數據作為 stream 處理。

注意事項:

  1. 由於沒有db.csv樣本,我無法正確測試
  2. pd.read_csv支持decimal=','參數,所以最好使用它。 但我仍在復制您的代碼行為,以便您可以在其他情況下使用它(例如,去除逗號 - 組分隔符)
  3. 下面的代碼沒有做任何on_bad_lines="skip"
from convtools import conversion as c
from convtools.contrib.tables import Table


float_cols = ["roe", "roi", "ros", "longitudine_dd", "latitudine_dd", "sfin", "cap_del", "cap_sott", "cap_vers", "eq_ec_1", "eq_eff_1", "eq_fin_1", "eq_liq_1", "eq_pat_1"]
date_cols = ["date_iscr", "date_init"]


def months_diff(a, b):
    return 12 * (a.year - b.year) + (a.month - b.month)


def parse_datetime(value, default):
    try:
        return datetime.strptime(value, "%Y-%m-%d")
    except (ValueError, TypeError):
        return default


rows_iter = (
    Table.from_csv(
        "db.csv", header=True, dialect=Table.csv_dialect(delimiter="\t")
    )
    .filter(
        c.and_(
            c.col("piva").is_not(None),
            c.col("code").is_not(None),
            c.col("provincia_cd").pipe(len) == 2,
            c("\.").not_in(c.col("ateco")),
        )
    )
    .update(
        **{
            column: c.col(column).call_method("replace", ",", ".")
            for column in float_cols
        },
        **{
            column: c.call_func(parse_datetime, c.col(column), default=None)
            for column in date_cols
        },
    )
    .update(
        delta=c.col("date_init").and_then(
            c.call_func(months_diff, date.today(), c.this)
        )
    )
    .into_iter_rows(dict)
)

結果是一個可迭代的 dicts,您可以將其直接提供給pd.DataFramepolars (無論如何)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM