added f strings and typing to frame.py
replaced old formatting with fstrings where possible

added typing hints to duplicated, drop_duplicates, reset_index
Thanks for the PR - can you run flake8 that will fix the github actions code checks CI failure: https://github.com/pandas-dev/pandas/pull/30021/checks?check_run_id=332186140#step:6:41 Hello @mck619! Thanks for updating this PR. We checked the lines you've touched for [PEP 8](https://www.python.org/dev/peps/pep-0008) issues, and found:





There are currently no PEP 8 issues detected in this Pull Request. Cheers! :beers: 

##### Comment last updated at 2019-12-06 00:05:07 UTC @mck619 looks like some tricky mypy failures. Flag me down at PyData and I'll help you out in person could try this as minimum to make mypy pass...

```diff
diff --git a/pandas/core/frame.py b/pandas/core/frame.py
index 6afd64f64..491c86999 100644
--- a/pandas/core/frame.py
+++ b/pandas/core/frame.py
@@ -15,6 +15,7 @@ import itertools
 import sys
 from textwrap import dedent
 from typing import (
+    Any,
     FrozenSet,
     Hashable,
     Iterable,
@@ -25,6 +26,7 @@ from typing import (
     Tuple,
     Type,
     Union,
+    cast,
 )
 import warnings
 
@@ -4192,7 +4194,7 @@ class DataFrame(NDFrame):
         inplace: bool = False,
         col_level: Hashable = 0,
         col_fill: Optional[Hashable] = "",
-    ) -> "DataFrame":
+    ) -> Optional["DataFrame"]:
         """
         Reset the index, or a level of it.
 
@@ -4220,8 +4222,8 @@ class DataFrame(NDFrame):
 
         Returns
         -------
-        DataFrame
-            DataFrame with the new index.
+        DataFrame or None
+            DataFrame with the new index or None if ``inplace=True``.
 
         See Also
         --------
@@ -4386,6 +4388,7 @@ class DataFrame(NDFrame):
                 new_index = self.index.droplevel(level)
 
         if not drop:
+            to_insert: Iterable[Tuple[Any, Optional[Any]]]
             if isinstance(self.index, ABCMultiIndex):
                 names = [
                     (n if n is not None else f"level_{i}")
@@ -4425,6 +4428,8 @@ class DataFrame(NDFrame):
         if not inplace:
             return new_obj
 
+        return None
+
     # ----------------------------------------------------------------------
     # Reindex-based selection methods
 
@@ -4590,7 +4595,7 @@ class DataFrame(NDFrame):
         subset: Optional[Union[Hashable, Sequence[Hashable]]] = None,
         keep: Union[str, bool] = "first",
         inplace: bool = False,
-    ) -> "DataFrame":
+    ) -> Optional["DataFrame"]:
         """
         Return DataFrame with duplicate rows removed.
 
@@ -4612,7 +4617,7 @@ class DataFrame(NDFrame):
 
         Returns
         -------
-        DataFrame
+        DataFrame or None
         """
         if self.empty:
             return self.copy()
@@ -4624,6 +4629,7 @@ class DataFrame(NDFrame):
             (inds,) = (-duplicated)._ndarray_values.nonzero()
             new_data = self._data.take(inds)
             self._update_inplace(new_data)
+            return None
         else:
             return self[-duplicated]
 
@@ -4675,6 +4681,9 @@ class DataFrame(NDFrame):
         ):
             subset = (subset,)
 
+        # needed for mypy since can't narrow types using np.iterable
+        subset = cast(Iterable, subset)
+
         # Verify all columns in subset exist in the queried dataframe
         # Otherwise, raise a KeyError, same as if you try to __getitem__ with a
         # key that doesn't exist.
@@ -6024,6 +6033,8 @@ class DataFrame(NDFrame):
             raise ValueError("columns must be unique")
 
         df = self.reset_index(drop=True)
+        # TODO: use overload to refine return type of reset_index
+        assert df is not None  # needed for mypy
         result = df[column].explode()
         result = df.drop([column], axis=1).join(result)
         result.index = self.index.take(result.index)
diff --git a/pandas/core/reshape/merge.py b/pandas/core/reshape/merge.py
index d671fff56..726a59ca8 100644
--- a/pandas/core/reshape/merge.py
+++ b/pandas/core/reshape/merge.py
@@ -126,7 +126,10 @@ def _groupby_and_merge(
                 on = [on]
 
             if right.duplicated(by + on).any():
-                right = right.drop_duplicates(by + on, keep="last")
+                _right = right.drop_duplicates(by + on, keep="last")
+                # TODO: use overload to refine return type of drop_duplicates
+                assert _right is not None  # needed for mypy
+                right = _right
         rby = right.groupby(by, sort=False)
     except KeyError:
         rby = None
```

May want to use overloads with `drop_duplicates` and `reset_index` to reduce additional asserts and code changes needed elsewhere.

May also want to be more precise with declaration of `to_insert`

Ideally, also find a way of avoiding the cast. Thanks @mck619 for the PR ! (and @simonjayhawkins for detailed comments) Thank you @WillAyd and @simonjayhawkins for all your help with my first PR!! Can't wait to contribute in a more helpful and meaningful manner in the future.