Nathan Tew
Nathan Tew

Reputation: 747

Pandas .at throwing ValueError: At based indexing on an integer index can only have integer indexers

So I have a df where I am extracting one value to store it in another df:

import pandas as pd

# Create data set
d = {'foo':[100, 111, 222], 
     'bar':[333, 444, 555]}
df = pd.DataFrame(d)

# Full dataframe:
print(df)

# Shows:
#    bar   foo 
# 0  333   100
# 1  444   111
# 2  555   222

df2=pd.DataFrame()
df2.loc[1,'Name'] = df[df.foo == 222]['foo']

#error: 
ValueError: Incompatible indexer with Series

I'm assuming the last line throws that error because df[df.foo == 222]['foo'] is a Series:

2    222
Name: foo, dtype: int64

So I'm trying to get the value itself. I used .at and got this:

print(df[df.foo == 222].loc[:,'bar'].at['bar'])

#ValueError: At based indexing on an integer index can only have integer indexers

From what I've read it's iat that uses integer indexers and at uses both label and integer, so what's going on here?

Upvotes: 8

Views: 26701

Answers (4)

Shifu
Shifu

Reputation: 41

.at will work with label indexing, not position indexing.
Example:

df.at(3,'ColName')

Returns value of ColName for 3rd row.

Upvotes: 0

Vasu Bandaru
Vasu Bandaru

Reputation: 11

The point at which you're using at, the data is a Pandas Series with integer Index, That is why your getting the mentioned error.

#ValueError: At based indexing on an integer index can only have integer indexers

If you check the index of the data, you'll see an index with value 2

df[df.foo == 222].loc[:,'bar'].index

#Int64Index([2], dtype='int64')

One of the correct method would be, as mentioned by coldspeed

df.loc[df.foo == 222].at[2,'bar']

#555

Upvotes: 0

cs95
cs95

Reputation: 402982

Using at with a boolean mask is considered bad form unless you can 100% guarantee only one row in the mask is true (otherwise, at fails).

The best thing to do is to use loc and take the first result.

df.loc[df.foo == 222, 'bar'].values[0]
555

For reference, at does not work because returns a single-row Series with a index [2]:

df[df.foo == 222].loc[:,'bar']

2    555
Name: bar, dtype: int64

At this point, at['bar'] makes no sense because it searches for "bar" in the index and bar isn't. What you should've done is

df[df.foo == 222].at[2, 'bar']
555

Upvotes: 7

meW
meW

Reputation: 3967

You can easily get the value using values

df2.loc[1,'Name'] = df[df.foo == 222]['foo'].values
df2

#   Name
# 1 222

Upvotes: 0

Related Questions