ENH: Add dtype argument to StringMethods get_dummies()
State: closed

Adding these args makes StringMethods get_dummies() similarly powerful to pd.get_dummies(), but usable in the common scenario that the strings are separated by some separator.

- [x] closes #47872
- [x] [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
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [x] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.


Labels:
name: Enhancement
name: Strings
description: String extension data type and string data

Comments:
@rhshadrach  Is this PR under review at all? I believe its a helpful change to a function with currently limited functionality.
I don't disagree with that. I was only adding trivial arguments to mimic the behavior of pd.get_dummies. In the interest of simplicity, I can remove all those args. However, I think dtype is a pretty critical behavior.
> I don't disagree with that. I was only adding trivial arguments to mimic the behavior of pd.get_dummies.

Ah, I see! Still, I think it might be better to deprecate `prefix`, `prefix_sep`, and `columns` from `pd.get_dummies` and rely on the user using `rename` and `concat` to accomplish their goal. Thanks for removing!
I previously had the pyarrow tests parametrized, but the td.skip_if_no decorator does not seem to work concurrently with the pytest parametrize decorator. So I split the pyarrow tests by types.
> I previously had the pyarrow tests parametrized, but the td.skip_if_no decorator does not seem to work concurrently with the pytest parametrize decorator. So I split the pyarrow tests by types.

The issue is just with parametrize - namely that `@pytest.mark.parametrize(..., [ArrowDtype(pa.uint8()])` requires `pa` be imported which fails when PyArrow is not installed. You can instead use the string alias, e.g. `"uint8[pyarrow]"`.
Just added the info to whatsnew.
> Can you also add a tests with strings:
> 
> ```python
> s = Series(["a|b", "a|c", np.nan])
> result = s.str.get_dummies("|", dtype=str)
> expected = DataFrame(
>     [["T", "T", "F"], ["T", "F", "T"], ["F", "F", "F"]],
>     columns=list("abc"),
>     dtype=str,
> )
> tm.assert_frame_equal(result, expected)
> ```

Is there any specific reason we want the expected result to use `"T"` and `"F"` for strings? (compared to `"True"` and `"False"` as actual string repr of bools, or `"1"` and `"0"` if we could actually cast the standard integer result to strings)
Looking in the code, I see the technical reason for it. `dtype=str` is translated to numpy's `U` type, but we first create an empty array to then fill in, and at that point numpy makes that more concrete as a `U1` type (length-1 strings), and then assining boolean True/False values into that array gives the resulting `"T"` and `"F"`.

Now, that doesn't look very intentional, and I also notice that with the pyarrow string backend, it has a different result. 
And with `pd.get_dummies()` (not the `.str.` variant), it seems we get yet another result:

```
In [3]: s = Series(["a", "b", "a", "c", np.nan])

In [4]: pd.get_dummies(s)
Out[4]: 
       a      b      c
0   True  False  False
1  False   True  False
2   True  False  False
3  False  False   True
4  False  False  False

In [5]: pd.get_dummies(s, dtype=str)
Out[5]: 
   a  b  c
0  1      
1     1   
2  1      
3        1
4  0  0  0
```

But that also looks wrong ... (at least inconsistent in empty string vs "0" for False cases depending on whether it was a missing value or not).

The `dtype` keyword in general is definitely useful, but I think mostly to ask for a different _numeric_ data type (like a smaller integer bitwidth), so we could maybe also just disallow asking for string dtype (that would also avoid having to decide which of those string results is the best ..)
> And with `pd.get_dummies()` (not the `.str.` variant), it seems we get yet another result:

I was under the impression that `pd.get_dummies(..., dtype=str)` would return T/F prior to this PR, but that doesn't seem to be the case. I'd be okay with raising on string dtype in `str.get_dummies` and deprecate `pd.get_dummies`.

@aaronchucarroll - would you be interested in doing a follow up addressing the above comments by @mroeschke and @jorisvandenbossche?
Yes, I could do a follow-up but it may take me a bit of time to get to it. We want to allow dtype for numeric types only and raise an error on string dtype arguments? I will open a PR soon for this.