Repository: pandas-dev/pandas

Issue:
Indices of df.describe(percentiles=np.linspace(...)) are mix of integers and decimal numbers
#### Code Sample, a copy-pastable example if possible

```python
import numpy as np
import pandas as pd
df = pd.DataFrame(columns=["a"], data=np.random.randint(10, size=30).reshape(-1, 1))
pct = np.linspace(0, 1, 20 + 1)
desc = df.describe(percentiles=pct)

print(desc.index)
print(desc.loc['25%'])
print(desc.loc['30%'])
```
#### Problem description
If desc.index is printed out, some percentile indexes are written as decimal numbers (e.g. 30.0%, 55.0%, 85.0%), while others are whole numbers (e.g. 35%, 70%, 100%). Printing percentiles of distribution therefore requires hardcoding some decimal numbers, e.g.
 
```python
print(desc.loc['0%'])
print(desc.loc['5%'])
print(desc.loc['10%'])
print(desc.loc['15.0%'])
print(desc.loc['20%'])
print(desc.loc['25%'])
print(desc.loc['30.0%'])
print(desc.loc['35%'])
print(desc.loc['40%'])
print(desc.loc['45%'])
print(desc.loc['50%'])
print(desc.loc['55.0%'])
print(desc.loc['60.0%'])
print(desc.loc['65%'])
print(desc.loc['70%'])
print(desc.loc['75%'])
print(desc.loc['80%'])
print(desc.loc['85.0%'])
print(desc.loc['90%'])
print(desc.loc['95%'])
print(desc.loc['100%'])
```

#### Expected Output
Indexes of percentiles should be either all whole numbers or either all decimal numbers.

#### Output of ``pd.show_versions()``

<details>
INSTALLED VERSIONS
------------------
commit: None
python: 3.5.2.final.0
python-bits: 64
OS: Linux
OS-release: 4.15.0-50-generic
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8
LOCALE: en_US.UTF-8

pandas: 0.24.2
pytest: None
pip: 19.1.1
setuptools: 41.0.1
Cython: None
numpy: 1.16.3
scipy: 1.2.1
pyarrow: None
xarray: None
IPython: 7.5.0
sphinx: None
patsy: None
dateutil: 2.8.0
pytz: 2019.1
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: 3.0.3
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: 0.7.3
lxml.etree: 3.5.0
bs4: 4.4.1
html5lib: 0.999
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: 2.8
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None
gcsfs: None
</details>



Discussion:
Makes sense. If you'd like to take a look would certainly welcome a PR
Would by my pleasure. I will follow up on this over this weekend.

Resolving patch:
diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py
--- a/pandas/io/formats/format.py
+++ b/pandas/io/formats/format.py
@@ -1246,7 +1246,7 @@ def format_percentiles(percentiles):
             raise ValueError("percentiles should all be in the interval [0,1]")
 
     percentiles = 100 * percentiles
-    int_idx = (percentiles.astype(int) == percentiles)
+    int_idx = np.isclose(percentiles.astype(int), percentiles)
 
     if np.all(int_idx):
         out = percentiles.astype(int).astype(str)


Test patch:
diff --git a/pandas/tests/frame/test_analytics.py b/pandas/tests/frame/test_analytics.py
--- a/pandas/tests/frame/test_analytics.py
+++ b/pandas/tests/frame/test_analytics.py
@@ -704,6 +704,17 @@ def test_describe_tz_values(self, tz_naive_fixture):
         result = df.describe(include='all')
         tm.assert_frame_equal(result, expected)
 
+    def test_describe_percentiles_integer_idx(self):
+        # Issue 26660
+        df = pd.DataFrame({'x': [1]})
+        pct = np.linspace(0, 1, 10 + 1)
+        result = df.describe(percentiles=pct)
+
+        expected = DataFrame(
+            {'x': [1.0, 1.0, np.NaN, 1.0, *[1.0 for _ in pct], 1.0]},
+            index=['count', 'mean', 'std', 'min', '0%', '10%', '20%', '30%',
+                   '40%', '50%', '60%', '70%', '80%', '90%', '100%', 'max'])
+        tm.assert_frame_equal(result, expected)
     # ---------------------------------------------------------------------
     # Reductions
 
diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py
--- a/pandas/tests/io/formats/test_format.py
+++ b/pandas/tests/io/formats/test_format.py
@@ -2740,6 +2740,14 @@ def test_format_percentiles():
         fmt.format_percentiles([0.1, 0.5, 'a'])
 
 
+def test_format_percentiles_integer_idx():
+    # Issue #26660
+    result = fmt.format_percentiles(np.linspace(0, 1, 10 + 1))
+    expected = ['0%', '10%', '20%', '30%', '40%', '50%',
+                '60%', '70%', '80%', '90%', '100%']
+    assert result == expected
+
+
 def test_repr_html_ipython_config(ip):
     code = textwrap.dedent("""\
     import pandas as pd