def merge_dfs(self, df1):
        """
        Description: takes new calculated data and replaces the corresponding data in self.df with the new input data preserving the most important metadata if they are not otherwise saved. Note this does not mutate self.df it simply returns the merged dataframe if you want to replace self.df you'll have to do that yourself.

        @param: df1 - first DataFrame whose data will preferentially be used.
        """

        if self.df.empty:
            return df1
        elif df1.empty:
            return self.df

        #copy to prevent mutation
        cdf2 = self.df.copy()

        #split data into types and decide which to replace
#        if replace_dir_or_int == 'dir' and 'method_codes' in cdf2.columns:
#            cdf2 = cdf2[cdf2['method_codes'].notnull()]
#            acdf2 = cdf2[cdf2['method_codes'].str.contains('LP-PI')]
#            mcdf2 = cdf2[cdf2['method_codes'].str.contains('LP-DIR')]
#        elif replace_dir_or_int == 'int' and 'method_codes' in cdf2.columns:
#            cdf2 = cdf2[cdf2['method_codes'].notnull()]
#            mcdf2 = cdf2[cdf2['method_codes'].str.contains('LP-PI')]
#            acdf2 = cdf2[cdf2['method_codes'].str.contains('LP-DIR')]
#        else:
#            mcdf2 = cdf2
#            acdf2 = pd.DataFrame(columns=mcdf2.columns)

        #get rid of stupid duplicates
#        [mcdf2.drop(cx,inplace=True,axis=1) for cx in mcdf2.columns if cx in df1.columns]

        #join the new calculated data with the old data of same type
        if self.dtype.endswith('s'): dtype = self.dtype[:-1]
        else: dtype = self.dtype
        index_name = dtype + "_name"
        for df in [df1, cdf2]:
            df.index.name = index_name
        mdf = df1.join(cdf2, how='outer', rsuffix='_remove', on=index_name)
        def keep_non_null_vals(column):
            extra_column = column + "_remove"
            if column in mdf.columns and extra_column in mdf.columns:
                mdf[column] = np.where(mdf[column].apply(lambda x: not_null(x, False)), mdf[column], mdf[extra_column])
        # merge values in the following columns
        # e.g., combine info from specimen + specimen_remove into specimen column
        for col in ['specimen', 'sample', 'site', 'location', 'lat', 'lon']:
            keep_non_null_vals(col)
        #drop duplicate columns if they were created
        [mdf.drop(col,inplace=True,axis=1) for col in mdf.columns if col.endswith("_remove")]
        #duplicates rows for some freaking reason
        mdf.drop_duplicates(inplace=True,subset=[col for col in mdf.columns if col != 'description'])
        #merge the data of the other type with the new data
#        mdf = mdf.merge(acdf2, how='outer')
        if dtype in mdf.columns:
            #fix freaking indecies because pandas
            mdf = mdf.set_index(dtype)
            #really? I wanted the index changed not a column deleted?!?
            mdf[dtype] = mdf.index
            mdf.index.name = index_name
            mdf.sort_index(inplace=True)
        return mdf