# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: 'Python 3.10.1 (''.venv'': venv)'
#     language: python
#     name: python3
# ---

# # PANDAS vs SAS
#
# Para los usuarios potenciales que provienen de SAS, se pretende mostrar cómo se realizarían las diferentes operaciones de SAS en pandas.
#
# General terminology translation
#
# |pandas   |SAS        |
# |:-------:|:---------:|
# |DataFrame|data set   |
# |column   |variable   |
# |row      |observation|
# |groupby  |BY-group   |
# |NaN      |.          |
#
# ## Dataframe
#
# Un `DataFrame` en pandas es análogo a un conjunto de datos SAS: una fuente de datos bidimensional con columnas etiquetadas que pueden ser de diferentes tipos. Como se mostrará en este notebook, casi cualquier operación que se pueda aplicar a un conjunto de datos utilizando el paso DATA de SAS, también se puede realizar en pandas.
#
# ## Series
#
# Una `Series` es la estructura de datos que representa una columna de un `DataFrame`. SAS no tiene una estructura de datos separada para una sola columna, pero en general, trabajar con una Serie es similar a hacer referencia a una columna en el paso DATOS.
#
# ## Index
#
# Cada `DataFrame` y `Series` tiene un `Index`, que son etiquetas en las filas de los datos. SAS no tiene un concepto exactamente análogo. Las filas de un conjunto de datos esencialmente no están etiquetadas, excepto un índice entero implícito al que se puede acceder durante el paso `DATA` (`_N_`).
#
# ## Copies vs. in place operations
#
# La mayoría de las operaciones de pandas devuelven copias de Series/DataFrame. Para hacer que los cambios se "mantengan", deberá asignarlos a una nueva variable:
#
# ```
# sorted_df = df.sort_values("col1")
# ```
#
# o sobrescribir el original:
#
# ```
# df = df.sort_values("col1")
# ```
#
# ### Nota
#
# Verá un argumento de palabra clave `inplace=True` disponible para algunos métodos:
#
# ```
# df.sort_values("col1", inplace=True)
# ```
#
# **SU USO NO ES RECOMENDADO**

# ## Constructing a DataFrame from values
#
# ```
#         data df;
#             input x y;
#             datalines;
#             1 2
#             3 4
#             5 6
#             ;
#         run;
# ```

# +
import pandas as pd
import numpy as np

df = pd.DataFrame({"x": [1, 3, 5], "y": [2, 4, 6]})

df
# -

# ## Reading external data
#
# ```
#     proc import datafile='tips.csv' dbms=csv out=tips replace;
#         getnames=yes;
#     run;
# ```

# +
url = ("https://raw.github.com/pandas-dev/"
"pandas/main/pandas/tests/io/data/csv/tips.csv"
)

tips = pd.read_csv(url)

tips
# -

# Al igual que `PROC IMPORT`, `read_csv` puede tomar una serie de parámetros para especificar cómo se deben analizar los datos. Por ejemplo, si los datos estuvieran delimitados por tabuladores y no tuvieran nombres de columna, el comando pandas sería:
#
# ```
# tips = pd.read_csv("tips.csv", sep="\t", header=None)
#
# # alternatively, read_table is an alias to read_csv with tab delimiter
#
# tips = pd.read_table("tips.csv", header=None)
# ```

# ## Limitación de salida
#
# En SAS:
#
# ```
#     proc print data=df(obs=5);
#     run;
# ```

tips.head(5)

# De forma predeterminada, los pandas truncarán la salida de los marcos de datos grandes para mostrar la primera y la última fila. Esto se puede anular cambiando las opciones de pandas o usando DataFrame.head() o DataFrame.tail()
#
# ## Exportando datos
#
# El inverso de `PROC IMPORT` en SAS es `PROC EXPORT`
#
# ```
#     proc export data=tips outfile='tips2.csv' dbms=csv;
#     correr;
# ```
#
# De manera similar, en pandas, lo opuesto a `read_csv` es `to_csv()`, y otros formatos de datos siguen una API similar.

tips.to_csv(".\\csv\\tips2.csv")

# ## Data operations
#
# ### Operations on columns
#
# ```
#     data tips;
#         set tips;
#         total_bill = total_bill - 2;
#         new_bill = total_bill / 2;
#     run;
# ```

# +
tips["total_bill"] = tips["total_bill"] - 2

tips["new_bill"] = tips["total_bill"] / 2

tips
# -

# ## Filter
#
# El filtrado en SAS se realiza con una instrucción `if` o `where` en una o más columnas.
#
# ```
#     data tips;
#         set tips;
#         if total_bill > 10;
#     run;
#
#     data tips;
#         set tips;
#         where total_bill > 10;
#         /* equivalent in this case - where happens before the
#           DATA step begins and can also be used in PROC statements */
#     run;
# ```

tips[tips["total_bill"] > 10]

# La declaración anterior simplemente pasa una Serie de objetos `True/False` al `DataFrame`, devolviendo todas las filas con `True`.

# +
is_dinner = tips["time"] == "Dinner"

is_dinner
# -

is_dinner.value_counts()

tips[is_dinner]

# ### `If/then` logic
#
# En SAS, la lógica `if/then` se puede usar para crear nuevas columnas.
#
# ```
#     data tips;
#         set tips;
#         format bucket $4.;
#
#         if total_bill < 10 then bucket = 'low';
#         else bucket = 'high';
#     run;
# ```
#
#
# La misma operación en pandas se puede realizar utilizando el método `where` de `numpy`. 

# +
tips["bucket"] = np.where(tips["total_bill"] < 10, "low", "high")

tips
# -

# ### Date functionality
#
# SAS proporciona una variedad de funciones para realizar operaciones en columnas de `date/datetime `.
#
# ```
#     data tips;
#         set tips;
#         format date1 date2 date1_plusmonth mmddyy10.;
#         date1 = mdy(1, 15, 2013);
#         date2 = mdy(2, 15, 2015);
#         date1_year = year(date1);
#         date2_month = month(date2);
#         * shift date to beginning of next interval;
#         date1_next = intnx('MONTH', date1, 1);
#         * count intervals between dates;
#         months_between = intck('MONTH', date1, date2);
#     run;
#
# ```
#
# Las operaciones equivalentes de pandas se muestran a continuación. Además de estas funciones, pandas es compatible con otras funciones de series temporales que no están disponibles en SAS base (como el remuestreo y las compensaciones personalizadas); consulte la documentación de series temporales para obtener más detalles.
#

# +
tips["date1"] = pd.Timestamp("2013-01-15")

tips["date2"] = pd.Timestamp("2015-02-15")

tips["date1_year"] = tips["date1"].dt.year

tips["date2_month"] = tips["date2"].dt.month

tips["date1_next"] = tips["date1"] + pd.offsets.MonthBegin()

tips["months_between"] = tips["date2"].dt.to_period("M") - tips["date1"].dt.to_period("M")



tips[["date1", "date2", "date1_year", "date2_month", "date1_next", "months_between"]]
# -

# ### Selección de columnas
#
# SAS proporciona palabras clave en el paso DATA para seleccionar, eliminar y cambiar el nombre de las columnas.
#
# ```
#         data tips;
#             set tips;
#             keep sex total_bill tip;
#         run;
#
#         data tips;
#             set tips;
#             drop sex;
#         run;
#
#         data tips;
#             set tips;
#             rename total_bill=total_bill_2;
#         run;
# ```
# Las mismas operaciones se expresan en pandas a continuación

# +
# Keep certain columns

tips[["sex", "total_bill", "tip"]]

# +
# Drop a column

tips.drop("sex", axis=1)

# +
# Rename a column

tips.rename(columns={"total_bill": "total_bill_2"})
# -

# ### Sorting by values
#
# Sorting en SAS es realizado via `PROC SORT`
#
# ```
#     proc sort data=tips;
#         by sex total_bill;
#     run;
# ```

# +
tips = tips.sort_values(["sex", "total_bill"])

tips
# -

# ## Merging
#
# Las siguientes tablas se utilizarán en los ejemplos de combinación: 

# +
df1 = pd.DataFrame({"key": ["A", "B", "C", "D"], "value": np.random.randn(4)})

df1

# +
df2 = pd.DataFrame({"key": ["B", "D", "D", "E"], "value": np.random.randn(4)})

df2
# -

# En SAS, los datos deben ordenarse explícitamente antes de fusionarse. Se logran diferentes tipos de join usando las variables dummy para rastrear si se encontró una coincidencia en uno o ambos frames.
#
# ```
#     proc sort data=df1;
#         by key;
#     run;
#
#     proc sort data=df2;
#         by key;
#     run;
#
#     data left_join inner_join right_join outer_join;
#         merge df1(in=a) df2(in=b);
#
#         if a and b then output inner_join;
#         if a then output left_join;
#         if b then output right_join;
#         if a or b then output outer_join;
#     run;
# ```
#
# `pandas DataFrames` tiene un método `merge()`, que proporciona una funcionalidad similar. No es necesario ordenar los datos con anticipación, y los diferentes tipos de combinación se logran a través de la palabra clave how.

# +
inner_join = df1.merge(df2, on=["key"], how="inner")

inner_join

# +
left_join = df1.merge(df2, on=["key"], how="left")

left_join

# +
right_join = df1.merge(df2, on=["key"], how="right")

right_join

# +
outer_join = df1.merge(df2, on=["key"], how="outer")

outer_join
# -

# ### Group By
#
# El `PROC SUMMARY` de SAS se puede utilizar para agrupar por una o más variables clave y calcular agregaciones en columnas numéricas.
#
# ```
#     proc summary data=tips nway;
#         class sex smoker;
#         var total_bill tip;
#         output out=tips_summed sum=;
#     run;
#
# ```
#
# pandas proporciona un mecanismo de agrupación flexible que permite agregaciones similares.

# +
tips_summed = tips.groupby(["sex", "smoker"])[["total_bill", "tip"]].sum()

tips_summed
# -

# ## Interoperabilidad de datos
#
# `pandas` proporciona un método `read_sas()` que puede leer datos SAS guardados en formato binario `XPORT` o `SAS7BDAT`.
#
# ```
#     libname xportout xport 'transport-file.xpt';
#     data xportout.tips;
#         set tips(rename=(total_bill=tbill));
#         * xport variable names limited to 6 characters;
#     run;
# ```
#
# En pandas>
#
# ```
# df = pd.read_sas("transport-file.xpt")
# df = pd.read_sas("binary-file.sas7bdat")
# ```
#
#
# # MÁS INFORMACIÓN
#
# Consulte la documentación oficial [aquí](https://pandas.pydata.org/pandas-docs/stable/getting_started/comparison/comparison_with_sas.html#compare-with-sas)



StarcoderdataJupyterScriptsDedupFiltered