import pandas as pd
from datetime import datetime
from pyinaturalist import (
get_observations,
get_taxa_by_id,
get_places_by_id
)
import ipyplot
from itertools import isliceMis fotos del año 2007
El 2007 es uno de los años en los que he estado menos activo en mi hobby de fotografiar plantas y animales, y son pocas las observaciones que he subido a iNaturalist.
Para poner estas observaciones de 2007 en contexto temporal de mis contribuciones a iNat, pueden revisar este gráfico
Este documento me permite visualizar las fotos que ya están en iNaturalist y así evitar subir fotos por duplicado. Lamentablemente solo tomamos unas pocas fotos en algunos de los viajes de este año, y entre ellas no he encontrado muchas fotos para contribuir en iNaturalist.
Cargar módulos en Python
Importamos los módulos necesarios:
Y declaramos una función útil para leer los datos temporales de la respuesta del API de iNat:
def as_date(x):
if type(x) == str:
y = datetime.strptime(x, "%Y-%m-%d").date()
else:
y = datetime.date(x)
return(y)Descargar datos
Usamos get_observations con un intervalo de fechas que incluye todo el año 2010:
observations = get_observations(user_id='NeoMapas',
d1="2007-01-01",
d2="2007-12-31",
per_page=1000)Este número aumenta a medida que cargamos observaciones en iNat:
len(observations['results'])18
Usamos este loop para guardar la información básica de cada observación:
records=list()
places=list()
taxa=list()
for obs in observations['results']:
main_record = {
'uuid':obs['uuid'],
'species guess': obs['species_guess'],
'location': obs['place_guess'],
'month': obs['observed_on_details']['month'],
'Fecha_obs': as_date(obs['observed_on']),
'Fecha_reg': as_date(obs['created_at'])
}
if len(obs['observation_photos'])>0:
main_record['url'] = obs['observation_photos'][0]['photo']['url'].replace("square","medium")
main_record['attribution'] = obs['observation_photos'][0]['photo']['attribution']
records.append(main_record)
for pid in obs['place_ids']:
place_record = {
'uuid': obs['uuid'],
'place id': pid
}
places.append(place_record)
for tid in obs['ident_taxon_ids']:
taxon_record = {
'uuid': obs['uuid'],
'taxon id': tid
}
taxa.append(taxon_record)Y las transformamos en un marco de datos con información espacial para usar con geopandas:
inat_obs=pd.DataFrame(records)
places = pd.DataFrame(places)
taxa = pd.DataFrame(taxa)Resumen de las observaciones por estado
Primero combinamos la información de iNat con los estados de Venezuela. Usamos la función sjoin_nearest porque algunas observaciones provienen de la costa y las coordenadas de especies amenazadas están protegidas.
all_taxa=list(set(taxa['taxon id']))
def chunk(it, size):
it = iter(it)
return iter(lambda: tuple(islice(it, size)), ())for slc in chunk(all_taxa,30):
taxa_query = get_taxa_by_id(slc, rank_level=[70,60,50,40,30,20,10])
for res in taxa_query['results']:
qry = taxa.loc[taxa['taxon id'] == res['id'],'uuid']
inat_obs.loc[inat_obs.uuid.isin(qry), res['rank']] = res['name']all_places=list(set(places['place id']))
response = get_places_by_id(all_places,
admin_level=[10,0])
for res in response['results']:
qry = places.loc[places['place id'] == res['id'],'uuid']
if res['admin_level'] == 10:
level='state'
elif res['admin_level'] == 0:
level='country'
inat_obs.loc[inat_obs.uuid.isin(qry), level] = res['name']Agrupamos las observaciones por la localidad y mes, y obtenemos una tabla resumen de las observaciones del año:
aggfuns = {
'species guess': 'count',
}
inat_obs.groupby(['country','state','month']).agg(aggfuns).unstack().fillna(0)| species guess | ||||
|---|---|---|---|---|
| month | 4 | 5 | 7 | |
| country | state | |||
| Panama | Colón | 2.0 | 0.0 | 0.0 |
| Panamá | 0.0 | 3.0 | 0.0 | |
| Panamá Oeste | 0.0 | 4.0 | 0.0 | |
| Venezuela | Miranda | 6.0 | 0.0 | 0.0 |
| Zulia | 0.0 | 0.0 | 3.0 | |
Filtrar por fecha
Con estas líneas de código podemos filtrar por fecha de observación:
ss = inat_obs['month'] == 5
images = inat_obs.loc[ss,'url']
labels = inat_obs.loc[ss,'species guess']
ipyplot.plot_images(list(images), list(labels), max_images=60,)list(images)[ 'https://inaturalist-open-data.s3.amazonaws.com/photos/543829421/medium.jpg', 'https://inaturalist-open-data.s3.amazonaws.com/photos/543829142/medium.jpg', 'https://inaturalist-open-data.s3.amazonaws.com/photos/543828914/medium.jpg', 'https://inaturalist-open-data.s3.amazonaws.com/photos/543828220/medium.jpg', 'https://inaturalist-open-data.s3.amazonaws.com/photos/543828109/medium.jpg', 'https://inaturalist-open-data.s3.amazonaws.com/photos/543828012/medium.jpg', 'https://inaturalist-open-data.s3.amazonaws.com/photos/543827613/medium.jpg' ]
Progreso
Aquí se puede ver el progreso que he hecho en cargar las fotos del año 2008, creo que estas son todas las que tengo respaldadas:
aggfuns = {
'Fecha_obs': ["min", "max"],
'location': ['count',pd.Series.nunique],
'species guess': [pd.Series.nunique],
}
inat_obs.groupby('Fecha_reg').agg(aggfuns)| Fecha_obs | location | species guess | |||
|---|---|---|---|---|---|
| min | max | count | nunique | nunique | |
| Fecha_reg | |||||
| 2024-11-08 | 2007-04-29 | 2007-04-29 | 2 | 1 | 2 |
| 2025-07-28 | 2007-04-24 | 2007-07-30 | 16 | 6 | 14 |
Todas las observaciones
Y cierro aquí con todas las imágenes de las observaciones de este año:
images = inat_obs.sort_values('Fecha_obs')['url']
labels = inat_obs.sort_values('Fecha_obs')['species guess']
ipyplot.plot_images(list(images), list(labels), max_images=200,)