<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用 Pandas 做 ETL,不要太快

          共 3348字,需瀏覽 7分鐘

           ·

          2022-02-22 19:05

          久違了,朋友們,來篇干貨。

          ETL 的全稱是 extract, transform, load,意思就是:提取、轉(zhuǎn)換、 加載。ETL 是數(shù)據(jù)分析中的基礎(chǔ)工作,獲取非結(jié)構(gòu)化或難以使用的數(shù)據(jù),把它變?yōu)楦蓛?、結(jié)構(gòu)化的數(shù)據(jù),比如導(dǎo)出 csv 文件,為后續(xù)的分析提供數(shù)據(jù)基礎(chǔ)。

          本文對電影數(shù)據(jù)做 ETL 為例,分享一下 Pandas 的高效使用。完整的代碼請在公眾號「Python七號」回復(fù)「etl」獲取。

          1、提取數(shù)據(jù)

          這里從電影數(shù)據(jù) API 請求數(shù)據(jù)。在開始之前,你需要獲得 API 密鑰來訪問 API可以在這里[1]找到獲取密鑰的說明。

          一旦你有了密鑰,需要確保你沒有把它直接放入你的源代碼中,因此你需要創(chuàng)建 ETL 腳本的同一目錄中創(chuàng)建一個名為 config.py 的文件,將此放入文件:

          #config.py
          api_key?=?

          如果要將代碼發(fā)布到任何地方,應(yīng)該將 config.py 放入 .gitignore 或類似文件中,以確保它不會被推送到任何遠程存儲庫中。

          還可以將 API 密鑰存儲為環(huán)境變量,或使用其他方法隱藏它。目標是保護它不暴露在 ETL 腳本中。

          現(xiàn)在創(chuàng)建一個名為 tmdb.py 的文件,并導(dǎo)入必要的依賴:

          import?pandas?as?pd
          import?requests
          import?config

          向 API 發(fā)送單個 GET 請求的方法。在響應(yīng)中,我們收到一條 JSON 記錄,其中包含我們指定的 movie_id:

          API_KEY?=?config.api_key
          url?=?'https://api.themoviedb.org/3/movie/{}?api_key={}'.format(movie_id,?API_KEY)

          r?=?requests.get(url)

          這里我們請求 6 部電影,電影 movie_id 從 550 到 555 不等。我們創(chuàng)建一個循環(huán),一次請求每部電影一部,并將響應(yīng)附加到列表中:

          response_list?=?[]
          API_KEY?=?config.api_key

          for?movie_id?in?range(550,556):
          ??url?=?'https://api.themoviedb.org/3/movie/{}?api_key={}'.format(movie_id,?API_KEY)
          ??r?=?requests.get(url)
          ??response_list.append(r.json())

          現(xiàn)在我們拿到了 response_list 這樣復(fù)雜冗長的 JSON 數(shù)據(jù),這里使用 from_dict() 從記錄中創(chuàng)建 Pandas 的 DataFrame 對象:

          df?=?pd.DataFrame.from_dict(response_list)

          如果在 jupyter 上輸出一下 df,你會看到這樣一個數(shù)據(jù)幀:

          至此,數(shù)據(jù)提取完畢。

          2、轉(zhuǎn)換

          我們并不需要提取數(shù)據(jù)的所有這些列,所以接下來選擇我們需要使用的列。

          假如以下列是我們感興趣的:

          budget
          id
          imdb_id
          genres
          original_title
          release_date
          revenue
          runtime

          創(chuàng)建一個名為 df_columns 的列名稱列表,以便從主數(shù)據(jù)幀中選擇所需的列。

          df_columns?=?['budget',?'genres',?'id',?'imdb_id',?'original_title',?'release_date',?'revenue',?'runtime']

          請注意,有一個 genres 列(表示電影的體裁,類型)是長這樣的:

          這是一個 JSON 格式的列,我們希望擴展它。

          一種比較直觀的方法是將 genres 內(nèi)的分類分解為多個列,如果某個電影屬于這個分類,那么就在該列賦值 1,否則就置 0,就像這樣:

          現(xiàn)在我們用 pandas 來實現(xiàn)這個擴展效果。

          首先扁平化這個 JSON 列表:

          genres_list?=?df['genres'].tolist()
          flat_list?=?[item?for?sublist?in?genres_list?for?item?in?sublist]

          接下來,我們創(chuàng)建一個 genres_all 的臨時列,作為電影類別的代表,我們只需要 genres 內(nèi)的 name 屬性,稍后把它擴展為單獨的列:

          result?=?[]
          for?l?in?genres_list:
          ????r?=?[]
          ????for?d?in?l:
          ????????r.append(d['name'])
          ????result.append(r)
          df?=?df.assign(genres_all=result)

          為了完整的保存 genres 類型表,我們把它單獨做為一個表:電影類型表:

          df_genres?=?pd.DataFrame.from_records(flat_list).drop_duplicates()

          它是這樣的:

          接下來,將類型名稱附加到 df_columns 中,然后刪除 genres 列:

          df_columns?=?['budget',?'id',?'imdb_id',?'original_title',?'release_date',?'revenue',?'runtime']
          df_genre_columns?=?df_genres['name'].to_list()
          df_columns.extend(df_genre_columns)

          s?=?df['genres_all'].explode()
          df?=?df.join(pd.crosstab(s.index,?s))

          代碼的最后兩行,使用了 explode、crosstab 函數(shù)來擴展多個列,其效果就是如果電影屬于某個類型,該行的值就為 1,結(jié)果就是這樣:

          關(guān)于日期時間,我們希望將日期擴展為年、月、日、周,像這樣:

          那么以下代碼就是干這個的:

          df['release_date']?=?pd.to_datetime(df['release_date'])
          df['day']?=?df['release_date'].dt.day
          df['month']?=?df['release_date'].dt.month
          df['year']?=?df['release_date'].dt.year
          df['day_of_week']?=?df['release_date'].dt.day_name()
          df_time_columns?=?['id',?'release_date',?'day',?'month',?'year',?'day_of_week']

          3、加載

          加載就很簡單了,將 DataFrame 導(dǎo)出到 excel 或者 csv 即可。

          df[df_columns].to_csv('tmdb_movies.csv',?index=False)
          df_genres.to_csv('tmdb_genres.csv',?index=False)
          df[df_time_columns].to_csv('tmdb_datetimes.csv',?index=False)

          如果要導(dǎo)出 excel,那么就用 to_excel 函數(shù)。

          最后的話

          Pandas 是處理 excel 或者數(shù)據(jù)分析的利器,ETL 必備工具,本文以電影數(shù)據(jù)為例,分享了 Pandas 的常見用法,如果有幫助的話還請點個在看給更多的朋友,再不濟,點個贊也行。

          獲取完整代碼,公眾號「Python七號」回復(fù)「etl」獲取。

          最近在視頻號更新 Python 教程,學(xué) Python 的朋友可以關(guān)注下視頻號「編程小妙招」,就這樣,祝你學(xué)有所成。

          參考資料

          [1]

          這里: https://developers.themoviedb.org/3/getting-started/authentication


          瀏覽 56
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  www.操.com | 亚洲最黄电影 | 黄片免费观看永久免费 | 啪啪免费网址 | 国产精品6区 |