Paul Oyster
Paul Oyster

Reputation: 1223

How to set a value in a pandas DataFrame by mixed iloc and loc

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?

Upvotes: 31

Views: 15861

Answers (5)

Serge Stroobandt
Serge Stroobandt

Reputation: 31508

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']

Upvotes: 11

wotter
wotter

Reputation: 528

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

Upvotes: 0

Cappo
Cappo

Reputation: 76

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'

Upvotes: 0

travc
travc

Reputation: 1859

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.

Upvotes: 20

Robert Pollak
Robert Pollak

Reputation: 4165

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).

Upvotes: 3

Related Questions