# Accessing a Series¶

There are multiple ways to get to the data that is stored in your Series. Let's explore the balances Series.

Remember, the Series is indexed by username. The label is the username, the value is that user's balance.

In [1]:
# Setup
import pandas as pd

from utils import render

# Standard Python dictionary
test_balance_data = {
'pasan': 20.00,
'treasure': 20.18,
'ashley': 1.05,
'craig': 42.42,
}

balances = pd.Series(test_balance_data)


## Accessing by Index¶

A Series is ordered and indexable. It is zero based and you can access it by index, just like you would a list or array.

In [2]:
# Get the first user's balance
balances[0]

Out[2]:
20.0

Let's take a loook at the value returned.

In [3]:
type(balances[0])

Out[3]:
numpy.float64

The value is wrapped in a NumPy.Scalar so that it keeps it's data type and will play well with others.

The same positional indexing works just as it does with a standard list.

In [4]:
# The last balance
balances[-1]

Out[4]:
42.42

## Accessing by Label¶

Since a series is labelled, you can also access it much like you would a standard dict.

In [5]:
balances['pasan']

Out[5]:
20.0

### Series behave like dictionaries¶

In [6]:
try:
balances['kermit']
except KeyError:
render('Accessing a non-existent key raises a KeyError.')


Accessing a non-existent key raises a KeyError.

In [7]:
if balances.get('kermit') is None:
render('Use get to safely access keys. None is returned if key not present.')


Use get to safely access keys. None is returned if key not present.

In [8]:
if 'kermit' not in balances:
render('Use in to test the existence of a label.')


Use in to test the existence of a label.

## Accessing by Property¶

As long as your label meets variable naming constraints, it will be available as a property via dot notation on the Series!

In [9]:
balances.ashley

Out[9]:
1.05

## Accessing More Explicitly¶

We are using indexing which can either be a label or a positional index. This can get confusing. It's possible to be more explicit, which yes wise Pythonista, is always better than implicit.

A Series exposes a property named loc which can be used to explicitly lookup by label based indices only.

In [10]:
balances.loc['pasan']

Out[10]:
20.0

And to use the positional index explicitly, you can use the property iloc.

In [11]:
# Get the first value
balances.iloc[0]

Out[11]:
20.0

## Accessing by Slice¶

Like a NumPy array, a Series also provides a way to use slices to get different portions of the data, returned as a Series.

NOTE: Slicing with indices vs. labels behaves differently. The latter is inclusive.

### Slicing by Positional Index¶

When using positional indices, the slice is exclusive...

In [12]:
# Includes values from zero
#  up until **and not** including 3
balances.iloc[0:3]

Out[12]:
pasan       20.00
treasure    20.18
ashley       1.05
dtype: float64

### Slicing by Label¶

When using labels, the slice is inclusive...

In [13]:
# Include the values starting at 'pasan'
#  up until **and** including 'ashley'
balances.loc['pasan':'ashley']

Out[13]:
pasan       20.00
treasure    20.18
ashley       1.05
dtype: float64