Pandas read_csv de url

139

Estoy usando Python 3.4 con IPython y tengo el siguiente código. No puedo leer un archivo csv de la URL dada:

import pandas as pd
import requests

url="https://github.com/cs109/2014_data/blob/master/countries.csv"
s=requests.get(url).content
c=pd.read_csv(s)

Tengo el siguiente error

"Nombre de ruta de archivo esperado u objeto similar a un archivo, tipo"

¿Cómo puedo arreglar esto?

veneno
fuente
Necesitaría algo como, c=pd.read_csv(io.StringIO(s.decode("utf-8")))pero está recibiendo html de vuelta, no un archivo csv, por lo que no va a funcionar
Padraic Cunningham
3
Estoy bastante seguro de que la URL que desea es "https://raw.github.com/cs109/2014_data/blob/master/countries.csv".
kylie.a
@venom, eligió la respuesta más popular como la correcta
ibodi

Respuestas:

167

Actualizar

Desde los pandas 0.19.2ahora puede pasar la URL directamente .


Tal como sugiere el error, pandas.read_csvnecesita un objeto similar a un archivo como primer argumento.

Si desea leer el csv de una cadena, puede usar io.StringIO(Python 3.x) o StringIO.StringIO(Python 2.x) .

Además, para la URL: https://github.com/cs109/2014_data/blob/master/countries.csv : está obteniendo una htmlrespuesta, no un csv sin procesar, debe usar la URL proporcionada por el Rawenlace en la página de github para obtener una respuesta csv sin procesar, que es - https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv

Ejemplo

import pandas as pd
import io
import requests
url="https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv"
s=requests.get(url).content
c=pd.read_csv(io.StringIO(s.decode('utf-8')))
Anand S Kumar
fuente
¿Qué sucede si la respuesta es grande y quiero transmitirla en lugar de consumir memoria para el contenido codificado, el contenido descodificado y el objeto StringIO?
akaihola
9
En la última versión de pandas, puede dar la URL directamente, es decirc=pd.read_csv(url)
inodb
Curiosamente tengo una versión más nueva de pandas(0.23.4), pero no pude dar URL directamente. Esta respuesta me ayudó a que funcione.
Antti
1
"Actualizar desde pandas 0.19.2 ahora puede pasar la url directamente". A menos que no pueda porque necesita pasar argumentos de autenticación, en cuyo caso el ejemplo original es muy necesario.
Aaron Hall
Esta solución sigue siendo valiosa si necesita un mejor manejo de errores utilizando códigos HTTP que pueden ser devueltos por el objeto de solicitud (ej .: 500 -> puede ser necesario reintentar, 404 -> no reintentar)
JulienV
236

En la última versión de pandas ( 0.19.2) puedes pasar directamente la url

import pandas as pd

url="https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv"
c=pd.read_csv(url)
inodb
fuente
parece que el uso de este directamente en lugar de solicitudes directamente no utiliza las solicitudes-caché , incluso si se utiliza
Shadi
55
Ese código regresa urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)>debido al protocolo https que urllib no puede manejar.
multigoodverse
Para aquellos que usan Python 2, deberán usar Python 2.7.10+.
avelis
Parece haber algún problema al leer csv desde una URL. Leí el archivo una vez desde un almacenamiento local y una vez desde la URL, seguía recibiendo errores de la URL. Luego habilité error_bad_lines = False y se ignoró más del 99% de los datos. La URL es un enlace . Una vez que leí el archivo, se descubrió que la forma del conjunto de datos era (88,1), lo cual es completamente incorrecto
Rishik Mani
10

Como comenté, debe usar un objeto StringIO y descodificar, es decir, c=pd.read_csv(io.StringIO(s.decode("utf-8")))si usa solicitudes, debe descodificar ya que .content devuelve bytes si usó .text solo necesitaría pasar s como es s = requests.get(url).textc = pd.read_csv(StringIO(s)).

Un enfoque más simple es pasar la url correcta de los datos sin procesar directamente read_csv, no tiene que pasar un archivo como objeto, puede pasar una url para que no necesite solicitudes:

c = pd.read_csv("https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv")

print(c)

Salida:

                              Country         Region
0                             Algeria         AFRICA
1                              Angola         AFRICA
2                               Benin         AFRICA
3                            Botswana         AFRICA
4                             Burkina         AFRICA
5                             Burundi         AFRICA
6                            Cameroon         AFRICA
..................................

De los documentos :

filepath_or_buffer :

cadena o identificador de archivo / StringIO La cadena podría ser una URL. Los esquemas de URL válidos incluyen http, ftp, s3 y file. Para las URL de archivo, se espera un host. Por ejemplo, un archivo local podría ser file: //localhost/path/to/table.csv

Padraic Cunningham
fuente
1
¡Puedes alimentar la url directamente a los pandas read_csv! ¡por supuesto! ¡Esa es una solución mucho más simple que la que encontré! : D
PabTorre
1
@pabtorre, sí, un ejemplo de por qué leer los documentos es una buena idea.
Padraic Cunningham
6

El problema que tiene es que el resultado que obtiene en la variable 's' no es un csv, sino un archivo html. Para obtener el csv sin formato, debe modificar la url para:

' https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv '

Su segundo problema es que read_csv espera un nombre de archivo, podemos resolver esto usando StringIO del módulo io. El tercer problema es que request.get (url) .content entrega una secuencia de bytes, podemos resolver esto usando request.get (url) .text en su lugar.

El resultado final es este código:

from io import StringIO

import pandas as pd
import requests
url='https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv'
s=requests.get(url).text

c=pd.read_csv(StringIO(s))

salida:

>>> c.head()
    Country  Region
0   Algeria  AFRICA
1    Angola  AFRICA
2     Benin  AFRICA
3  Botswana  AFRICA
4   Burkina  AFRICA
PabTorre
fuente
2
url = "https://github.com/cs109/2014_data/blob/master/countries.csv"
c = pd.read_csv(url, sep = "\t")
Gursimran Singh
fuente
Proporcione una explicación de cómo funciona su solución.
Selim Yıldız
0

Para importar datos a través de URL en pandas simplemente aplique el código simple a continuación, funciona realmente mejor.

import pandas as pd
train = pd.read_table("https://urlandfile.com/dataset.csv")
train.head()

Si tiene problemas con los datos sin procesar, simplemente ponga 'r' antes de la URL

import pandas as pd
train = pd.read_table(r"https://urlandfile.com/dataset.csv")
train.head()
jain
fuente