25

Say I want a function that changes the value of a named column in a given row number of a DataFrame.
One option is to find the column's location and use iloc, like that:

def ChangeValue(df, rowNumber, fieldName, newValue):
    columnNumber = df.columns.get_loc(fieldName)
    df.iloc[rowNumber, columnNumber] = newValue

But I wonder if there is a way to use the magic of iloc and loc in one go, and skip the manual conversion.

Any ideas?

Paul Oyster
  • 1,133
  • 1
  • 12
  • 21
  • Why do you need the columnIndex? won't `df.loc[rowIndex, fieldName] = newValue` just work? – EdChum Aug 27 '15 at 20:28
  • Sorry for the confusion. The word 'index' was misleading, so I changed it. Assume the index is not relevant here. – Paul Oyster Aug 27 '15 at 20:34
  • The fact remains why do you need this, if your df index values are already represented by whatever `rowNumber` is and `fieldName` is a column already then my first comment will just work – EdChum Aug 27 '15 at 20:48
  • The index is irrelevant here. Example: I want to change a field in the first row of each group. The applied function f (in df.groupby(...).apply(f)) could use .iloc[0] and be ignorant about the index (which in this case would be the grouping fields). – Paul Oyster Aug 27 '15 at 20:54
  • I don't think you can do this as the indexing methods are specifically for either integer (iloc) or label based (loc) indexing, if you starting mixing both styles then you have to convert the integer<->label to do what you want – EdChum Aug 27 '15 at 21:01
  • I don't know what the question is, but here's a great answer regarding `iloc/loc/ix`, and is probably relevant to your question http://stackoverflow.com/questions/31593201/pandas-iloc-vs-ix-vs-loc-explanation Also, a small sample dataset would help here and make the question more concrete. – JohnE Aug 27 '15 at 21:05
  • @EdChum, are you idiot? – braaterAfrikaaner Jan 07 '23 at 16:31

5 Answers5

18

I suggest just using iloc combined with the Index.get_loc method. eg:

df.iloc[0:10, df.columns.get_loc('column_name')]

A bit clumsy, but simple enough.

MultiIndex has both get_loc and get_locs which takes a sequence; unfortunately Index just seems to have the former.

travc
  • 1,788
  • 1
  • 18
  • 9
6

Using loc

One has to resort to either employing integer location iloc all the way —as suggested in this answer,— or using plain location loc all the way, as shown here:

df.loc[df.index[[0, 7, 13]], 'column_name']
Serge Stroobandt
  • 28,495
  • 9
  • 107
  • 102
3

According to this answer,

ix usually tries to behave like loc but falls back to behaving like iloc if the label is not in the index.

So you should especially be able to use df.ix[rowNumber, fieldname] in case type(df.index) != type(rowNumber).

Community
  • 1
  • 1
Robert Pollak
  • 3,751
  • 4
  • 30
  • 54
0

Even it does not hold for each case, I'd like to add an easy one, if you are looking for top or bottom entries:

    df.head(1)['column_name']  # first entry in 'column_name'
    df.tail(5)['column_name']  # last 5 entries in 'column_name'
Cappo
  • 66
  • 7
0

Edit: doing the following is not a good idea. I leave the answer as a counter example.

You can do this:

df.iloc[rowNumber].loc[fieldName] = newValue

Example

import pandas as pd

def ChangeValue(df, rowNumber, fieldName, newValue):
    df.iloc[rowNumber].loc[fieldName] = newValue

df = pd.DataFrame([[0, 2, 3], [0, 4, 1], [10, 20, 30]],
                  index=[4, 5, 6], columns=['A', 'B', 'C'])
print(df)
    A   B   C
4   0   2   3
5   0   4   1
6  10  20  30

ChangeValue(df, 1, "B", 999)
print(df)
    A    B   C
4   0    2   3
5   0  999   1
6  10   20  30

But be careful, if newValue is not the same type it does not work and will fail silently

ChangeValue(df, 1, "B", "Oops")
print(df)
    A    B   C
4   0    2   3
5   0  999   1
6  10   20  30

There is some good info about working with columns data types here: Change column type in pandas

wotter
  • 518
  • 5
  • 22
  • 2
    Your answer suggests an [assignment with chained indexing](https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy) which will result in a [`SettingWithCopy` warning](https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#why-does-assignment-fail-when-using-chained-indexing). This should be avoided by all means. – Serge Stroobandt Aug 16 '21 at 08:19
  • Yes knowing a bit more about pandas now, I agree. – wotter Aug 24 '21 at 16:00