Tengo un marco de datos df que se ve así donde no se establece ningún índice:

df.head()

    year    month   inch    mm
0   1981    2       0.00    0.000
1   1981    3       4.82    122.428
2   1981    4       6.45    163.830
3   1981    5       5.03    127.762
4   1981    6       1.25    31.750

(1) Primero, quiero seleccionar solo los años entre 1987 y 2017.

(2) Entonces quiero agrupar por año para meses seleccionados: MAM (por lo tanto, 3-5), JJAS (6-9) y OND (10-12) y sumar la columna mm para estos meses.

El resultado podría verse así:

year   season   mm
1981   MAM      360
1981   JJAS     167
...

No estoy seguro de cómo hacer la parte 1, pero sé que para la parte 2 necesito convertir la columna month en un objeto de fecha y hora.

Y luego definiría los meses de intereses por:

MAM = df.iloc[df.index.month.isin(np.r_[3:6])]
JJAS = df.iloc[df.index.month.isin(np.r_[6:10])]
OND = df.iloc[df.index.month.isin(np.r_[10:13])]

Pero por ahora recibo el error AttributeError: 'RangeIndex' object has no attribute 'month'.

¡Gracias de antemano!

0
JAG2024 13 nov. 2017 a las 03:35

2 respuestas

La mejor respuesta

La primera parte es bastante sencilla. Utilice pd.Series.between:

df = df[df.year.between(1987, 2017)]

Si year no está ordenado, recomiendo ordenar df primero, use sort_values(subset='year') para hacerlo.

Para la siguiente parte, una solución implicaría generar un mapeo dict y luego usar map para convertir month a su cadena mapeada, y agrupar en eso.

mapping = {3 : 'MAM', 4 : 'MAM', 5 : 'MAM', 6 : 'JJAS' ,... } # complete this
r = df.groupby(['year', df.month.map(mapping)]).sum()
1
cs95 13 nov. 2017 a las 00:50

Aquí hay un enfoque ligeramente diferente: use year y month para construir un índice, luego groupby() con una UDF.

Datos de ejemplo:

N = 10
years = pd.date_range("1981", "2017", freq="A").year
dates = np.random.choice(years, size=N, replace=True)
months = np.random.choice(range(1,13), size=N, replace=True)
inches = np.random.randint(1,20, size=N)
mm = np.random.randint(1,100, size=N)
data = {"year":dates, "month":months, "inch":inches, "mm":mm}
df = pd.DataFrame(data)

df
   inch  mm  month  year
0    19  31     12  1990
1     8  71      9  1986
2     5  85      2  2009
3    17   8     12  2005
4    10  14     12  1987
5     7  87      2  1982
6     8  59      2  2004
7     8  74      8  2016
8     5   6      6  1993
9     3   7     12  1982

Ahora realice un subconjunto según el año y cree el índice:

mask = df.year.between(1987, 2017)
df.index = df.apply(lambda x: pd.to_datetime("{0} {1}".format(x.year, x.month), 
                                             format="%Y %m"), axis=1)

Luego groupby con year y una función de separación de meses:

def month_gb(x):
    if x.month in range(3,6):
        return 'MAM'
    elif x.month in range(6,10):
        return 'JJAS'
    elif x.month in range(10,13):
        return 'OND'

df.loc[mask].groupby(["year", month_gb]).mm.sum()

year      
1987  OND     14
1990  OND     31
1993  JJAS     6
2005  OND      8
2016  JJAS    74
Name: mm, dtype: int64
1
andrew_reece 13 nov. 2017 a las 01:28