0

Lets say I have a dataframe A with attribute called 'score'. I can modify the 'score' attribute of the second row by doing:

tmp = A.loc[2]

tmp.score = some_new_value

A.loc[2] = tmp

But I cant do it like this:

A.loc[2].score = some_new_value

Why ?

Very Confused
  • 35
  • 1
  • 5

2 Answers2

2

It will be hard to reproduce your case, because Pandas does not guarantee, when using chained indexing, whether the operation will return a view or a copy of the dataframe.

When you access a "cell" of the dataframe by

A.loc[2].score

you are actually performing two steps: first .loc and then .score (which is essentially chained indexing). The Pandas documentation has a nice post about it here.

The simplest way to prevent this is by consistently using .loc or .iloc to access the rows/columns you need and reassigning the value. Therefore, I would recommend always using either

A.loc[2, "score"] = some_new_value

or

A.at[2, "score"] = some_new_value

This kind of indexing + setting will be translated "under the hood" to:

A.loc.__setitem__((2, 'score'), some_new_value) # modifies A directly

instead of an unreliable chain of __getitem__ and __setitem__.

tania
  • 2,104
  • 10
  • 18
  • 1
    Thanks very much for your answer. I tried @user2640045's code and it did indeed work so I was very confused as to why the same thing didn't work for me. – Very Confused Oct 23 '20 at 14:29
0

Let's show an example:

import pandas as pd
dict_ = {'score': [1,2,3,4,5,6], 'other':'a'}
A = pd.DataFrame(dict_)
A

Dataframe:

    score   other
0   1       a
1   2       a
2   3       a
3   4       a
4   5       a
5   6       a

Now you can do the following, and the values are actually saved:

A.loc[2,'score'] = 'Heyyyy'
A

Dataframe:

    score   other
0   1       a
1   2       a
2   Heyyyy  a
3   4       a
4   5       a
5   6       a
jlb_gouveia
  • 603
  • 3
  • 11