Reputation: 2012
Coming from R, I naively tried
dfE_fitted['E_after'] = dfE_fitted['E_before']
That gave me
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
Fair enough, I'll try that then:
dfE_fitted.loc[:,'E_after'] = dfE_fitted['E_before']
This gives me
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/indexing.py:337: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
self.obj[key] = _infer_fill_value(value)
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/indexing.py:517: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
self.obj[item] = s
What am I doing horribly wrong?
Upvotes: 6
Views: 2912
Reputation: 294488
It isn't how you are doing your assignment. It's how you constructed dfE_fitted
. You constructed it in such a way so as to be a "copy" of something else. The recommendation to use .loc
is intended to be used in the construction of dfE_fitted
. Even then, using .loc
isn't a guarantee. You can still have a "is_copy" flag after using .loc
However, I can't see how you did that. Best I can do is recommend that you do
dfE_fitted = dfE_fitted.copy()
This will detangle the "copy" relationship and you can proceed to assign as you were.
dfE_fitted['E_after'] = dfE_fitted['E_before']
Working example
df = pd.DataFrame(dict(A=[1, 2], E_before=[3, 4], E_after=[5, 6]))
# Notice how I constructed this
dfE_fitted = df[['E_before']]
Then I try
dfE_fitted['E_after'] = dfE_fitted['E_before']
I get
However, had I constructed dfE_fitted
like this:
# Notice I used `.loc` like what was recommended
dfE_fitted = df.loc[:, ['E_before']]
I can do the following with no warning:
dfE_fitted['E_after'] = dfE_fitted['E_before']
You can tell if a dataframe is a "copy" by looking at its is_copy
attribute. If it is a copy, it will return a
<weakref at 0x1188d94f8; to 'DataFrame' at 0x1184bf898>
Which evaluates to True
bool(dfE_fitted.is_copy)
True
Otherwise, if it isn't a "copy" it is None
and evaluates to False
Upvotes: 9