Repository: dwavesystems/dimod

Issue:
Export SampleSet object to Pandas df
**Application**
It would be useful for Pandas users to be able to export the `SampleSet`/`Response` objects into a pandas dataframe.

**Proposed Solution**
```
samples = dimod.ExactSolver().sample_ising(h, J)
df = samples.to_pandas_dataframe()
```


Discussion:

Patch:
diff --git a/dimod/sampleset.py b/dimod/sampleset.py
index 9b5dc365..41ff5c1c 100644
--- a/dimod/sampleset.py
+++ b/dimod/sampleset.py
@@ -770,6 +770,37 @@ class SampleSet(Iterable, Sized):
         from dimod.io.json import sampleset_decode_hook
         return sampleset_decode_hook(obj, cls=cls)
 
+    ###############################################################################################
+    # Export to dataframe
+    ###############################################################################################
+
+    def to_pandas_dataframe(self):
+        """Convert a SampleSet to a Pandas DataFrame
+
+        Returns:
+            :obj:`pandas.DataFrame`
+
+        Examples:
+            >>> samples = dimod.SampleSet.from_samples([{'a': -1, 'b': +1, 'c': -1},
+                                                        {'a': -1, 'b': -1, 'c': +1}],
+                                                       dimod.SPIN, energy=-.5)
+            >>> samples.to_pandas_dataframe()
+               a  b  c  energy  num_occurrences
+            0 -1  1 -1    -0.5                1
+            1 -1 -1  1    -0.5                1
+
+        """
+        import pandas as pd
+
+        df = pd.DataFrame(self.record.sample, columns=self.variables)
+        for field in sorted(self.record.dtype.fields):  # sort for consistency
+            if field == 'sample':
+                continue
+
+            df.loc[:, field] = self.record[field]
+
+        return df
+
 
 def _samples_dicts_to_array(samples_dicts):
     """Convert an iterable of samples where each sample is a dict to a numpy 2d array. Also


Test patch:
diff --git a/tests/test_sampleset.py b/tests/test_sampleset.py
index bf2d23af..9ce1a7e5 100644
--- a/tests/test_sampleset.py
+++ b/tests/test_sampleset.py
@@ -21,6 +21,13 @@ import numpy as np
 import dimod
 
 
+try:
+    import pandas as pd
+    _pandas = True
+except ImportError:
+    _pandas = False
+
+
 class TestSampleSet(unittest.TestCase):
     def test_from_samples(self):
 
@@ -158,3 +165,16 @@ class TestSampleSetSerialization(unittest.TestCase):
         s = json.dumps(samples.to_serializable())
         new_samples = dimod.SampleSet.from_serializable(json.loads(s))
         self.assertEqual(samples, new_samples)
+
+
+@unittest.skipUnless(_pandas, "no pandas present")
+class TestSampleSet_to_pandas_dataframe(unittest.TestCase):
+    def test_simple(self):
+        samples = dimod.SampleSet.from_samples(([[-1, 1, -1], [-1, -1, 1]], 'abc'),
+                                               dimod.SPIN, energy=[-.5, .5])
+        df = samples.to_pandas_dataframe()
+
+        other = pd.DataFrame([[-1, 1, -1, -.5, 1], [-1, -1, 1, .5, 1]],
+                             columns=['a', 'b', 'c', 'energy', 'num_occurrences'])
+
+        pd.testing.assert_frame_equal(df, other, check_dtype=False)