【问题标题】:Combining all csv files from Github Repository Link and make it a one csv file合并来自 Github Repository Link 的所有 csv 文件并使其成为一个 csv 文件
【发布时间】:2021-12-16 17:48:20
【问题描述】:

我想从下面的 Github 存储库链接中收集所有 csv 文件,并希望将其设为新的 csv 文件(用于数据清理目的):

https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_daily_reports

这样我的新csv 文件将包含所有日期的数据。

使用以下命令,我将只能加载 01-01-2021.csv。

import numpy as np
import pandas as pd
import requests

df = pd.read_csv ('https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports/01-01-2021.csv')

df.head()

如何一次加载所有csv文件?

【问题讨论】:

  • 你为什么不把它们一一加载以便合并它们?
  • 您要下载并加载。还是直接从url加载?
  • @LakpaTamang 我想直接从 url 加载 csv 文件。
  • @UlrichEckhardt。我想直接从 url 加载 csv 文件。 (想要制作一个动态代码,以便它也适用于新的上传)。这是 covid19 每日报告的回购

标签: python pandas csv github data-analysis


【解决方案1】:

这是一个简短的解决方案,使用 pandasrequestsBeautifulSoup 过滤所有 csv 链接:

import pandas as pd
import requests
from bs4 import BeautifulSoup, SoupStrainer

html = requests.get('https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_daily_reports')

dfs = []
for link in BeautifulSoup(html.text, parse_only=SoupStrainer('a')):
    if hasattr(link, 'href') and link['href'].endswith('.csv'):
        url = 'https://github.com'+link['href'].replace('/blob/', '/raw/')
        dfs.append(pd.read_csv(url))
df = pd.concat(dfs)

注意。测试代码,这在约 12 分钟内运行并产生 2300506 行 × 21 列的最终数据帧。理想情况下,应该添加一个多线程来并行下载多个文件(合理地,不要被服务器踢)

【讨论】:

    【解决方案2】:

    您提供的链接包含格式为month-day-year.csv 的csv 文件名。所以我做了一个循环来创建一个文件名并直接从给定的 URL 加载 csv。除非网站具有 csv 文件的随机命名约定,否则这应该可以工作。

    years = [2020, 2021]
    months = [month for month in range(1, 13)]
    days = [day for day in range(1, 31)]
    URL = 'https://raw.githubusercontent.com/CSSEGISandData/COVID- 
    19/master/csse_covid_19_data/csse_covid_19_daily_reports'
    all_files = []
    for year in years:
        for month in months:
            month = str(month).zfill(2)
            for day in days:
                day = str(day).zfill(2)
                print(f"{month}-{day}-{year}.csv")
                df = pd.read_csv(URL + f"/{month}-{day}-{year}.csv")
                all_files.append(df)
            final_csv_file = pd.concat(all_files, axis=0, ignore_index=True)
    

    这是我从上述源代码中获得的输出快照。但是在这里,我只循环了两个元素 1,2 的日期和月份以及 2021 年。只要网站具有非随机命名约定,这应该可以工作。

    【讨论】:

    • 好的!这看起来不错。让我检查!但是代码似乎对我不起作用!?收到“HTTPError:HTTP 错误 404:未找到”错误。您的进口商品?
    • 正如我所说,此错误表示该文件不存在于该 URL 中。文件名是使用循环自动创建的,程序会在 URL 中查找相同的文件名。 URL 中可能缺少某些具有特定文件名的 CSV 文件。您可以检查URL中文件的顺序并修改循环。
    【解决方案3】:

    给你!您可以指定开始日期和结束日期以从它们之间的这些日期获取所有数据。这还会检查该特定日期的 url 是否存在,并且只有当它是有效的 url 时,才会将其添加到最终数据框中。

    import requests
    import pandas as pd
    
    
    def is_leap_year(year):
        # checks if the current year is leap year
    
        """
            params:
                year - int
            
            returns:
                bool
        """
    
        if((year%4==0 and year%100!=0) or (year%400==0)):
            return True
        else:
            return False
    
    
    def split_date(date_str):
        # Splits the date into month, day and year
    
        """
            params:
                date_str - str (mm-dd-yyyy)
            
            returns:
                month - int
                day - int
                year - int
        """
    
        month, day, year = list(int(x) for x in date_str.split("-")) # For US standards, for rest of the world feel free to swap month and day
        return month, day, year
    
    
    def generate_dates(start_date, end_date):
        # This doesn't validate the dates and it is assumed that the start_date and end_dates both are valid dates with the end date > start_date
        # This generates all dates bw start date and end date and also takes into account leap year as well
    
        """
            params:
                start_date - str (mm-dd-yyyy)
                end_date - str (mm-dd-yyyy)
            
            returns:
                dates - list of strings of dates between start_date and end_date
        """
    
        dates = []
        start_month, start_day, start_year = split_date(start_date)
        end_month, end_day, end_year = split_date(end_date)
        
        year = start_year
        while(year<=end_year):
            month = start_month if(year==start_year) else 1
            max_month = end_month if(year==end_year) else 12
            while(month<=max_month):
                day = start_day if(year==start_year) else 1
                if(month==2):
                    max_day = 29 if(is_leap_year(year)) else 28
                else:
                    max_day = 31 if(start_month in [1,3,5,7,8,10,12]) else 30
                if(year==end_year and month==end_month):
                    max_day = end_day
                while(day<=max_day):
                    new_date = f"{month}-{day}-{year}"
                    dates.append(new_date)
                    day+=1
                month+=1
            year+=1
    
            return dates
    
    
    def check_if_url_is_valid(url):
        # This checks if the url is valid through the python requests library, by making a GET request. if the url is present and valid then it returns status code in (200-300)
    
        """
            params:
                url - str
            
            returns:
                bool
        """
    
        r = requests.get(url)
        if(r.status_code in range(200,300)):
            return True
        else:
            return False
            
    
    def to_df(base_url, start_date, end_date):
        # Takes all the generated dates, creates a url for each date through the base url and then tries to download it, else prints out an error message
    
        """
            params:
                base_url - str it should be of the format "https://github.com/{}.csv" where the {} will be used for string formatting and different dates will be put into it
    
                returns:
                    final_df - pd.DataFrame 
        """
    
        files = []
        dates = generate_dates(start_date, end_date)
        for date in dates:
            url = base_url.format(date)
            valid_url = check_if_url_is_valid(url)
            if(valid_url):
                df = pd.read_csv(url)
                files.append(df)
            else:
                print(f"Could not download {date} data as it may be unavailable")
        final_df = pd.concat(files)
        print(f"\n Downloaded {len(files)} files!\n")
        return final_df
    

    更新:

    这是相同的 Google Colab 链接 - https://colab.research.google.com/drive/19ysmJ2wWaiEpzGae7XqOSPa-FfNZqza3?usp=sharing

    【讨论】:

    • 我刚知道python datetime库可以生成日期bw start_date和end_date,所以你可以通过使用它来显着减少总代码大小
    • 那你为什么不更新你的答案呢? ;)
    • 我饿了,从早上开始就没吃东西了:)我稍后会更新!
    • 好的@Pranav!你已经付出了相当大的努力。太好了!
    【解决方案4】:

    签出pd.concat

    假设您拥有所有文件链接:

    dfs = []
    for l in links:
        df = pd.read_csv(l)
        dfs.append(df)
    final_df = pd.concat(dfs)
    

    【讨论】:

    • 实际上,主要问题是从 url 加载以 .csv 结尾的文件名(不是任何本地驱动器)。不适合我。
    猜你喜欢
    • 1970-01-01
    • 2018-03-30
    • 2019-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    相关资源
    最近更新 更多