Pandas read_csv depuis l'URL

139

J'utilise Python 3.4 avec IPython et j'ai le code suivant. Je ne parviens pas à lire un fichier csv à partir de l'URL donnée:

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)

J'ai l'erreur suivante

"Nom du chemin de fichier attendu ou objet de type fichier, type obtenu"

Comment puis-je réparer cela?

venin
la source
Vous auriez besoin de quelque chose comme c=pd.read_csv(io.StringIO(s.decode("utf-8")))mais vous récupérez html pas un fichier csv donc cela ne fonctionnera pas
Padraic Cunningham
3
Je suis assez certain que l'URL que vous souhaitez est "https://raw.github.com/cs109/2014_data/blob/master/countries.csv".
kylie.a
@venom, a choisi la réponse la plus populaire comme la bonne
ibodi

Réponses:

167

Mettre à jour

Depuis les pandas, 0.19.2vous pouvez maintenant simplement passer l'URL directement .


Tout comme l'erreur le suggère, pandas.read_csvnécessite un objet semblable à un fichier comme premier argument.

Si vous souhaitez lire le csv à partir d'une chaîne, vous pouvez utiliser io.StringIO(Python 3.x) ou StringIO.StringIO(Python 2.x) .

De plus, pour l'URL - https://github.com/cs109/2014_data/blob/master/countries.csv - vous obtenez une htmlréponse, pas un csv brut, vous devez utiliser l'URL fournie par le Rawlien dans la page github pour obtenir une réponse csv brute, qui est - https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv

Exemple -

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
la source
Que faire si la réponse est volumineuse et que je souhaite la diffuser au lieu de consommer de la mémoire pour le contenu codé, le contenu décodé et l'objet StringIO?
akaihola
9
Dans la dernière version de pandas, vous pouvez donner directement l'URL, c'estc=pd.read_csv(url)
inodb
Curieusement, j'ai une version plus récente de pandas(0.23.4), mais je ne pouvais pas donner directement l'URL. Cette réponse m'a aidé à faire fonctionner cela.
Antti
1
"Mise à jour de pandas 0.19.2, vous pouvez maintenant simplement passer directement l'URL." Sauf si vous ne pouvez pas car vous devez passer des arguments d'authentification, auquel cas l'exemple d'origine est indispensable.
Aaron Hall
Cette solution reste intéressante si vous avez besoin d'une meilleure gestion des erreurs en utilisant des codes HTTP qui peuvent être retournés par l'objet de requête (ex: 500 -> une nouvelle tentative peut être nécessaire, 404 -> aucune nouvelle tentative)
JulienV
236

Dans la dernière version de pandas ( 0.19.2), vous pouvez directement passer l'url

import pandas as pd

url="https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv"
c=pd.read_csv(url)
inodb
la source
il semble que l'utilisation de ceci directement au lieu de requêtes directement n'utilise pas le cache de requêtes même s'il est utilisé
shadi
5
Ce code retourne à urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)>cause du protocole https que urllib ne peut pas gérer.
multigoodverse
Pour ceux qui utilisent Python 2, vous devrez utiliser Python 2.7.10+.
avelis
Il semble y avoir un problème de lecture de csv à partir d'une URL. J'ai lu le fichier une fois à partir d'un stockage local et une fois à partir d'URL, j'ai continué à recevoir des erreurs d'URL. J'ai ensuite activé error_bad_lines = False et plus de 99% des données ont été ignorées. L'URL est un lien . Une fois que j'ai lu le fichier, la forme de l'ensemble de données s'est avérée être (88,1), ce qui est complètement faux
Rishik Mani
10

Comme je l'ai commenté, vous devez utiliser un objet StringIO et décoder, c'est-à c=pd.read_csv(io.StringIO(s.decode("utf-8")))- dire si vous utilisez des requêtes, vous devez décoder en tant que .content renvoie des octets si vous avez utilisé .text, il vous suffirait de passer s tel quel s = requests.get(url).textc = pd.read_csv(StringIO(s)).

Une approche plus simple consiste à transmettre l'URL correcte des données brutes directement à read_csv, vous n'avez pas à passer un fichier comme un objet, vous pouvez passer une URL pour ne pas avoir besoin de requêtes du tout:

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

print(c)

Production:

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

À partir de la documentation :

filepath_or_buffer :

chaîne ou descripteur de fichier / StringIO La chaîne peut être une URL. Les schémas d'URL valides incluent http, ftp, s3 et file. Pour les URL de fichiers, un hôte est attendu. Par exemple, un fichier local pourrait être file: //localhost/path/to/table.csv

Padraic Cunningham
la source
1
Vous pouvez envoyer l'URL directement aux pandas read_csv! bien sûr! c'est une solution bien plus simple que celle que j'ai trouvée! : D
PabTorre
1
@pabtorre, oui, un exemple de pourquoi la lecture de la documentation est une bonne idée.
Padraic Cunningham le
6

Le problème que vous rencontrez est que la sortie que vous obtenez dans la variable 's' n'est pas un csv, mais un fichier html. Afin d'obtenir le csv brut, vous devez modifier l'url en:

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

Votre deuxième problème est que read_csv attend un nom de fichier, nous pouvons le résoudre en utilisant StringIO du module io. Le troisième problème est que request.get (url) .content délivre un flux d'octets, nous pouvons le résoudre en utilisant le request.get (url) .text à la place.

Le résultat final est ce code:

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))

production:

>>> c.head()
    Country  Region
0   Algeria  AFRICA
1    Angola  AFRICA
2     Benin  AFRICA
3  Botswana  AFRICA
4   Burkina  AFRICA
PabTorre
la source
2
url = "https://github.com/cs109/2014_data/blob/master/countries.csv"
c = pd.read_csv(url, sep = "\t")
Gursimran Singh
la source
Veuillez expliquer le fonctionnement de votre solution.
Selim Yıldız le
0

Pour importer des données via une URL dans les pandas, appliquez simplement le code ci-dessous, cela fonctionne mieux.

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

Si vous rencontrez des problèmes avec des données brutes, mettez simplement «r» avant l'URL

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