DOC: Improve to_string() docstring to clarify that missing values are not passed through formatters
State: closed

## Summary
The current docstring for `to_string()` does not provide detail on how missing values are handled when using `formatters`.

This change adds an additional block to the `formatters` docstring explaining that `formatters` are **not** invoked for missing values. It also provides some guidance on how per-column formatting of missing values can be achieved.

### Background
This issue came to my attention while fixing a bug likely caused by a misunderstanding of how `to_string()` handles missing values. Specifically, formatters were assumed to be invoked on all values, including missing ones (which is not the case).

### Further issues
- It is slightly unclear to me how broadly this behaviour applies (I've seen it with `DataFrame.to_string()`, and the implementation appears to be generic). I could be wrong though.
- **Possible bug:** `NDFrame.to_latex()` takes a parameter called `formatters`, but following that through leads to the function `_to_latex_via_styler()` which **does not use the formatters parameter**!?
This looks like a potentially incomplete implementation without annotation (at `pandas/core/generic.py` , line ~3519). I can raise an issue for that separately if desired.

### Checks
~~- [ ] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature~~
Not applicable: no new code.

- [ ] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
  - Most tests passed. Exhaustive pre-commit suite did not complete due to failure of a check _completely unrelated to this change_ (incorrect type passed to `BaseBlockManager.copy()` in `pandas/core/generic.py`).

~~- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.~~
Not applicable: no new code.

~~- [ ] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.~~
Not applicable: this is just an improvement to documentation of existing functionality.


Labels:
name: Docs
name: Styler
description: conditional formatting using DataFrame.style
name: Stale

Comments:
What do you think about moving much of the current content in this PR to the User Guide:

https://pandas.pydata.org/docs/dev/user_guide/io.html#writing-a-formatted-string

and then linking to that from the docstring? 
Thanks for the review @datapythonista and suggestion @rhshadrach 😃

I agree what I've got feels overlong for a docstring, and probably makes more sense in the main docs.
I've shorted the docstring and added notes to the IO tools doc page.

Including a link in the docstring feels a bit clunky, though I can't see a good alternative. The other option would be saying `see 'Writing a formatted string' in the 'IO tools' section of the user guide`, and that is both long and less helpful. 🤷
/preview
Website preview of this PR available at: https://pandas.pydata.org/preview/pandas-dev/pandas/57545/
/preview
> /preview

The preview needs that the documentation is built in the CI. Seems like the documentation job failed because of warnings:

```
/home/runner/work/pandas/pandas/pandas/core/frame.py:docstring of pandas.core.frame.DataFrame.to_html:31: ERROR: Unknown target name: "io.formatting".
/home/runner/work/pandas/pandas/pandas/core/frame.py:docstring of pandas.core.frame.DataFrame.to_html:35: ERROR: Unknown target name: "io.formatting".
/home/runner/work/pandas/pandas/pandas/core/frame.py:docstring of pandas.core.frame.DataFrame.to_string:31: ERROR: Unknown target name: "io.formatting".
/home/runner/work/pandas/pandas/pandas/core/frame.py:docstring of pandas.core.frame.DataFrame.to_string:35: ERROR: Unknown target name: "io.formatting".
```

If you get the CI green, at least for the docs job, the previewer will work.
I think I've fixed all my issues.
The doc build is still breaking in the GH action, but due to something I don't think I caused:

`Doc Build and Upload` > `Test website`
```
  File "/home/runner/micromamba/envs/test/lib/python3.10/site-packages/pluggy/_manager.py", line 342, in _verify_hook
    raise PluginValidationError(
pluggy._manager.PluginValidationError: Plugin 'pytest_cython' for hook 'pytest_collect_file'
hookimpl definition: pytest_collect_file(path, parent)
Argument(s) {'path'} are declared in the hookimpl but can not be found in the hookspec
```
> The doc build is still breaking in the GH action, but due to something I don't think I caused:

pytest released today; guessing it's related to that.

Edit: pytest yanked the release, rerunning the builds.
Looks like many of the other tests failed due to CircleCI deprecating a load of Ubuntu images yesterday:
https://status.circleci.com/incidents/m04y1p0l3f3n

Edit: one of the other test failures was due to a test mismatch with `dateutil` 2.9 ([fixed upstream](https://github.com/pandas-dev/pandas/commit/c3ae17d04d3993e1c3e4c0f8824fde03b8c9beac), merged in).

Edit: merging in upstream again, looks like the test error about numpy arrays with copy=false has been addressed [here](https://github.com/pandas-dev/pandas/commit/b89f1d0d05f4c9f360985abc6bda421d73bae85f). Hopefully this'll fix the last test failure.
_bump_
@rhshadrach I think everything is now addressed. If you're happy with it can you update your review to remove the requested changes flag?
This pull request is stale because it has been open for thirty days with no activity. Please [update](https://pandas.pydata.org/pandas-docs/stable/development/contributing.html#updating-your-pull-request) and respond to this comment if you're still interested in working on this.
Thanks for the pull request, but it appears to have gone stale. If interested in continuing, please merge in the main branch, address any review comments and/or failing tests, and we can reopen.