{"record":{"id":"0e136acb57f1ae64","repo":"pandas-dev/pandas","slug":"bins-argument-only-works-with-numeric-data","errorCode":null,"errorMessage":"bins argument only works with numeric data.","messagePattern":"bins argument only works with numeric data\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/algorithms.py","lineNumber":1021,"sourceCode":"        DatetimeIndex,\n        Index,\n        Series,\n        TimedeltaIndex,\n    )\n\n    index_name = getattr(values, \"name\", None)\n    name = \"proportion\" if normalize else \"count\"\n\n    if bins is not None:\n        from pandas.core.reshape.tile import cut\n\n        if isinstance(values, Series):\n            values = values._values\n\n        try:\n            ii = cut(values, bins, include_lowest=True)\n        except TypeError as err:\n            raise TypeError(\"bins argument only works with numeric data.\") from err\n\n        # count, remove nulls (from the index), and but the bins\n        result = ii.value_counts(dropna=dropna)\n        result.name = name\n        result = result[result.index.notna()]\n        result.index = result.index.astype(\"interval\")\n        result = result.sort_index()\n\n        # if we are dropna and we have NO values\n        if dropna and (result._values == 0).all():\n            result = result.iloc[0:0]\n\n        # normalizing is by len of all (regardless of dropna)\n        normalize_denominator = len(ii)\n\n    else:\n        normalize_denominator = None\n        if is_extension_array_dtype(values):","sourceCodeStart":1003,"sourceCodeEnd":1039,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/algorithms.py#L1003-L1039","documentation":"Raised by value_counts_internal when bins is provided but the data cannot be binned. The bins path calls pandas.cut on the values; if cut raises TypeError (non-numeric data such as strings/datetimes that cut cannot handle), pandas re-raises this clearer message. Binning requires numeric data.","triggerScenarios":"s.value_counts(bins=5) where s is object/string/categorical non-numeric; df.value_counts(bins=...) on non-numeric columns; calling value_counts with bins on a boolean object array.","commonSituations":"Applying a generic value_counts(bins=N) helper to a DataFrame across all columns without filtering dtypes; data ingestion that left numeric columns as object dtype strings.","solutions":["Convert the data to numeric first: pd.to_numeric(s, errors='coerce').","Drop bins= for categorical/string data and use plain value_counts.","Restrict the bins call to numeric columns (select_dtypes(include='number'))."],"exampleFix":"# before\ns = pd.Series(['1', '2', '3', '4'])\ns.value_counts(bins=2)\n# after\npd.to_numeric(s, errors='coerce').value_counts(bins=2)","handlingStrategy":"validation","validationCode":"import pandas as pd\n\ndef value_counts_binned(s, bins):\n    if not pd.api.types.is_numeric_dtype(s):\n        s = pd.to_numeric(s, errors='coerce')\n    return s.value_counts(bins=bins)","typeGuard":"import pandas as pd\n\ndef is_binnable(s) -> bool:\n    return pd.api.types.is_numeric_dtype(s)","tryCatchPattern":"try:\n    return s.value_counts(bins=5)\nexcept TypeError:\n    return pd.to_numeric(s, errors='coerce').value_counts(bins=5)","preventionTips":["Ensure columns are numeric (select_dtypes(include='number')) before bins.","Coerce object columns with pd.to_numeric first.","Drop bins= for categorical/string value_counts."],"tags":["value-counts","bins","numeric","dtype"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}