Reputation: 35
I have a nested dictionary that is used as a lookup table to assign a value to a dataframe field. The code returns the following error when running:
TypeError: ("'Series' objects are mutable, thus they cannot be hashed", 'occurred at index 0')
I have tried using the get() function, yet receive the same error message.
The dictionary:
AdjFact= {
'Good':
{0: 0, 2010: 2.566, 2011: 1.77, 2012: 0.9658515212},
'Bad':
{0: 0, 2010: 3.222, 2011: 1.0423, 2012: 0.3534},
'Avg':
{0: 0, 2010: 1.30, 2011: 4.2, 2012: 1.01}
}
The code that looks for the value in the dictionary, uses a hardcoded value for the first dictionary value, and a value from a dataframe structure for the second dictionary value. It saves the value that has been retrieved from the nested dictionary (using the Year value from the row in the dataframe) to the dataframe's row as a variable called AdjustedResult.
def lookup(row,lval):
df= df_dict[[row['A'],row['B']]
df['AdjustedResult'] = AdjFact[lval][df['Year']]
. . . . . . . (more code deleted)
return Total, Diff
newdf[['TotalGood' , 'DiffGood']] = newdf.apply(lookup, lval='Good', axis=1).apply(pd.Series)
newdf[['TotalBad' , 'DiffBad']] = newdf.apply(lookup, lval='Bad', axis=1).apply(pd.Series)
newdf[['TotalAvg' , 'DiffAvg']] = newdf.apply(lookup, lval='Avg', axis=1).apply(pd.Series)
I don't particularly have to use the AdjFact dictionary, if a different lookup table (dataframe, etc) would work.
EDIT: added code below - just for testing purposes
I have hardcoded in a lot of the values and dummy dataframes below, just so that the logic of the code can be tested (i.e. the lookup function)
import pandas as pd
new_df = pd.DataFrame({"RowNum": [1,2,3,4,5,6],"A": ['Test1','Test2','Test2','Test1','Test1','Test2'],
"B":['D','D','MO','D','D','D'],"Year": [2020,2008,2010,2008,2010,2011]})
df_dict_temp = {('Test1','D'): pd.DataFrame({"Col1":[3,2,4,5,2], "Year":[0,0,2010,2010,2011]}),
('Test2','D'):pd.DataFrame(),
('Test2','MO'):pd.DataFrame({"Col1":[3,2,4,5,2], "Year":[0,0,2010,2010,2011]})
}
AdjFact= {
'Good':
{0: 0, 2010: 2.566, 2011: 1.77, 2012: 0.9658515212},
'Bad':
{0: 0, 2010: 3.222, 2011: 1.0423, 2012: 0.3534},
'Avg':
{0: 0, 2010: 1.30, 2011: 4.2, 2012: 1.01}
}
def lookup(row,lval):
m_df= df_dict_temp[row['A'],row['B']]
m_df['AdjustedResult'] = AdjFact[lval][m_df['Year']]
Total = 0
#df['Discount'].sum()
Diff = 0
#df['Value'] - df['Discount']
return Total, Diff
new_df[['TotalGood' , 'DiffGood']] = new_df.apply(lookup, lval='Good', axis=1).apply(pd.Series)
Upvotes: 1
Views: 158
Reputation: 375475
df['Year']
is a Series (which can't be hashed and therefore you can't look it up in a dict). I suspect you mean row['Year']
, the year for that particular row?
That is,
df['AdjustedResult'] = AdjFact[lval][df['Year']]
should read:
df['AdjustedResult'] = AdjFact[lval][row['Year']]
--
Update: with your latest example, it seems you want to lookup the value for each row (I missed that in the first example):
ipdb> m_df['Year'].map(AdjFact[lval])
0 0.000
1 0.000
2 2.566
3 2.566
4 1.770
Name: Year, dtype: float64
So you should use:
m_df['AdjustedResult'] = m_df['Year'].map(AdjFact[lval])
Upvotes: 1