Primero cargamos los dos archivos CSV que tenemos, correspondientes a los datos de los taxis amarillos y verdes. Podemos observar que dichos datasets no tienen las mismas dimensiones, teniendo el dataset de los taxis verdes más columnas.
#Importación de las librerias necesarias
import pandas as pd
from datetime import datetime
#Llamada al dataset con la información sobre los taxis verdes
filename = "green_monday.csv"
df_verdes = pd.read_csv(filename)
df_verdes.head()
#Llamada al dataset con la información sobre los taxis amarillos
filename = "taxis_monday.csv"
df_amarillos = pd.read_csv(filename)
df_amarillos.head()
Para cada uno de los datasets, vemos sus dimensiones y nombres de columna. Esto nos da información sobre qué columnas eliminar y cómo unificar los nombres de columna de ambos datasets
df_verdes.shape, df_verdes.columns.values
df_amarillos.shape, df_amarillos.columns.values
Eliminamos aquellas columnas únicas que solo están en uno de los dataset.
columns_drop_verdes = ['Ehail_fee', 'Trip_type ', 'type']
df_verdes.drop(columns_drop_verdes, inplace=True, axis=1)
df_amarillos.drop('Unnamed: 0.1', inplace=True, axis=1)
Creamos una nueva columna para ambos datasets. Esta establece la principal diferenciación entre ambos conjuntos de datos, su color.
df_verdes['color'] = "Verde"
df_amarillos['color'] = "Amarillo"
Concatenaremos las columnas comunes, renombrando las columnas del dataframe df_verdes con los mismos nombres que tiene el dataframe df_amarillos.
data = df_amarillos.merge(df_verdes.rename(columns={'lpep_pickup_datetime':'tpep_pickup_datetime',
'Lpep_dropoff_datetime':'tpep_dropoff_datetime',
'Passenger_count': 'passenger_count',
'Trip_distance': 'trip_distance',
'Pickup_longitude': 'pickup_longitude',
'Pickup_latitude': 'pickup_latitude',
'RateCodeID': 'RatecodeID',
'Store_and_fwd_flag': 'store_and_fwd_flag',
'Dropoff_longitude': 'dropoff_longitude',
'Dropoff_latitude': 'dropoff_latitude',
'Payment_type': 'payment_type',
'Fare_amount': 'fare_amount',
'Extra': 'extra',
'MTA_tax': 'mta_tax',
'Tip_amount': 'tip_amount',
'Tolls_amount': 'tolls_amount',
'Total_amount': 'total_amount',
}),how='outer')
#Dataframe con los datos de ambos datasets
data.head()
#Comprobación de que la combinación ha sido efectiva
data.shape
#Obtenemos infomación del dataframe creado
data.info()
#Más información sobre algunas variables del dataframe
data.describe()
#Comprobación de cuántas filas tienen valores negativos para total_amount
len(data[data["total_amount"]<0])
La comprobación anterior ya nos pone en alerta de que tendremos que eliminar algunas variables con valores negativos donde no debería (cantidad total, coste, propina...) pero antes de hacer esto, hay algunos de los nombres de columna del dataframe no son demasiado entendibles por lo que los renombraremos.
data = data.rename(columns={'Unnamed: 0': 'ID',
'VendorID': 'vendorID',
'tpep_pickup_datetime': 'pickup_datetime',
'tpep_dropoff_datetime': 'dropoff_datetime',
'passenger_count': 'numero_pasajeros',
'trip_distance': 'distancia',
'RatecodeID': 'ratecodeID',
'payment_type': 'tipo_pago',
'fare_amount': 'coste',
'tip_amount': 'propina',
'tolls_amount': 'peaje',
'improvement_surcharge': 'recargo_mejora',
'total_amount': 'cantidad_total',
'hora': 'pickup_hora'
})
Comprobamos si hay algún valor faltante en todo el dataframe
data.isnull().sum().sum()
Aquellas columnas con un único valor pueden ser eliminadas ya que no aportan ningún extra. Así, procedemos a identificarlas y eliminarlas.
#Identificación
for x in data.columns.values:
if len(data[x].unique()) == 1:
print(x)
#Eliminación
columns_drop = ['dia_semana','dia']
data.drop(columns_drop, inplace=True, axis=1)
#Tambien eliminamos la columna fecha ya que es la misma que "pickup_datetime"
data.drop('fecha', inplace=True, axis=1)
Saber cuánto duró cada trayecto es un dato bastante importante por lo que procedemos a su cálculo tanto en minutos como en segundos.
#Extracción de la hora a partir de la fecha
pickup_hora = [pickup_time.split(" ")[1] for pickup_time in data["pickup_datetime"]]
dropoff_hora = [dropoff_time.split(" ")[1] for dropoff_time in data["dropoff_datetime"]]
#Agregamos las horas de pickup y dropoff como columnas nuevas del dataset
data['pickup_hora'] = pd.Series(pickup_hora, index=data.index)
data['dropoff_hora'] = pd.Series(dropoff_hora, index=data.index)
#Bucle para cálculo de la duracion
duracion_segundos=[]
duracion_minutos=[]
date_format = "%Y-%m-%d %H:%M:%S"
for index, fecha in enumerate(data["pickup_datetime"]):
a = datetime.strptime(data["pickup_datetime"][index], date_format)
b = datetime.strptime(data["dropoff_datetime"][index], date_format)
c = b - a
segundos = c.total_seconds()
duracion_segundos.append(segundos)
minutos = c.total_seconds()/60
duracion_minutos.append(minutos)
data['duracion_segundos'] = pd.Series(duracion_segundos, index=data.index)
data['duracion'] = pd.Series(duracion_minutos, index=data.index)
data.head()
Estos pueden encontrarse en http://www.nyc.gov/html/tlc/downloads/pdf/data_dictionary_trip_records_yellow.pdf. Según el pdf, las siguientes columnas deberán tener sólo los siguientes valores:
Vamos a comprobar si esto es así.
#Comprobación de cuántos valores únicos tiene cada una de las variables anteriores
data["vendorID"].unique(), data["ratecodeID"].unique(), data['store_and_fwd_flag'].unique(), data['tipo_pago'].unique()
data[data["ratecodeID"]==99]
Algunos valores de la columna "ratecodeID" son valores numéricos diferentes a los que debería ser pero al ser tan poquitos, podemos sustituir estos valores por el valor 1 que corresponde a "Tarifa normal". También procedemos a cambiar todos los valores categóricos anteriores, ahora que sabemos con qué nombres descriptivos renombrarlos.
vendorID = ['Creative Mobile Technologies, LLC', 'VeriFone Inc']
ratecodeID = ['Tarifa normal', 'Aeropuerto JFK', 'Aeropuerto Newark', 'Aeropuerto Nassau or Westchester', 'Tarifa negociada', 'Viaje en grupo']
store_and_fwd_flag = ['store and forward trip', 'not a store and forward trip']
tipo_pago = ['Tarjeta', 'Efectivo', 'Sin cargos', 'Disputa', 'Desconocido', 'Viaje nulo']
data['vendorID'] = data['vendorID'].map({1: vendorID[0], 2: vendorID[1]})
data['ratecodeID'] = data['ratecodeID'].map({1: ratecodeID[0], 2: ratecodeID[1], 3: ratecodeID[2], 4: ratecodeID[3],
5: ratecodeID[4], 6: ratecodeID[5], 99: ratecodeID[0]})
data['store_and_fwd_flag'] = data['store_and_fwd_flag'].map({'Y': store_and_fwd_flag[0], 'N': store_and_fwd_flag[1]})
data['tipo_pago'] = data['tipo_pago'].map({1: tipo_pago[0], 2: tipo_pago[1], 3: tipo_pago[2], 4: tipo_pago[3]})
#Comprobación
data["vendorID"].unique(), data["ratecodeID"].unique(), data['store_and_fwd_flag'].unique(), data['tipo_pago'].unique()
Eliminamos todos aquellos datos con las siguientes características:
1) Pickups fuera del área de New York: Eliminamos todos aquellos datos con longitudes y latitudes fuera del área de New York ya que estamos haciendo el estudio justo dentro de esta ciudad.
2) Cuando el nº de pasajeros es 0.
3) Cuando el nº de pasajeros es mayor que 8 (máximo hay coches con 9 plazas: conductor + 8 pasajeros).
4) Trayectos donde la tarifa total, coste, propina o recargo por mejora sea <0.
5) Valores de extra y mta_tax diferentes a los que deberían de ser.
6) Trayectos donde la duración es > 300 (5 horas máximo conduciendo).
7) Trayectos donde la distancia recorrida sea > 600km (5h*120km/h).
Datos que NO eliminamos:
data = data[data["numero_pasajeros"] > 0]
data = data[data["numero_pasajeros"] < 9]
data = data[data["coste"] >= 0]
data = data[data["propina"] >= 0]
data = data[data["cantidad_total"] >= 0]
data = data[data["duracion"] < 300]
data = data[data["distancia"] >= 0]
data = data[data["distancia"] < 600]
data = data[data["recargo_mejora"] >= 0]
values = [0,0.5,1]
data = data.loc[data["extra"].isin(values)]
values_mta = [0,0.5]
data = data.loc[data["mta_tax"].isin(values_mta)]
#Puntos dentro de la ciudad de New York
data = data[data["pickup_latitude"] > 40.55]
data = data[data["pickup_latitude"] < 40.93]
data = data[data["pickup_longitude"] < -73.10]
data = data[data["pickup_longitude"] > -74.20]
data = data.reset_index(drop=True)
data.head()
#Comprobación
data[data["cantidad_total"]<0]
#Columna extra para saber más facilmente si el taxista recibió propina
lista=[]
for index, datetime in enumerate(data["propina"]):
if data["propina"][index]==0:
lista.append("No")
else:
lista.append("Si")
data["propina?"]= pd.Series(lista, index=data.index)
data.head()
Una vez terminada la limpieza, guardamos el dataframe limpio
data.to_csv("data_limpios.csv", sep=";", decimal=',', encoding='utf-8')