見出し画像

AhrefsのOrganicKeywordsデータのPosition changeをPolarsで処理できるように変換する

前回のnoteで、AhrefsのOrganic Keywordsからダウンロードしてきたデータでは「Positon change」にNewやLostの文字列が含まれていないため、CSV読み込み時に文字列型(pl.Utf8)として読み込まないといけないことを書きました。

しかしこのままでは順位変動の値が文字列になっていて、少し扱いづらいかなと思います。そこで今回は、Positon changeに入っている文字列を数値にするための方法を紹介します。

結論

AhrefsのCSVをread_csvで読み込んだあとで、previous_positionとcurrent_positionにfill_null(101)をしてから、previous_positionとcurrent_positionの差を計算すればOKです。

import pandas as pd
import polars as pl
from google.colab import files

uploaded = files.upload()

# CSVファイルからDataFrameを作成する
file_name = next(iter(uploaded))
df = pl.read_csv(file_name, dtypes={"Position change": pl.Utf8})
df.columns = [column_name.replace(' ', '_').lower() for column_name in df.columns]

# fill_nullで101位を設定したあとで、position_changeを計算する
df = df.with_columns(
    previous_position = pl.col("previous_position").fill_null(101),
    current_position = pl.col("current_position").fill_null(101),
).with_columns(
    position_change = pl.col("previous_position") - pl.col("current_position")
)

df

解説

AhrefsのOrganic KeywordsのCSVファイルは、順位が101位圏外だった場合には値が記載されていません(Polarsで読み込むとnullになっている)

そのため、読み込んだままのデータからposition_changeを計算しようとすると、比較順位・対象順位のどちらかが圏外だった場合には、順位の差分もnullになってしまいます。

# previous_positionもしくはcurrent_positionがnullだと、position_changeもnullになってしまう
df.with_columns(
    position_change = pl.col("previous_position") - pl.col("current_position")
).filter(
    pl.col("current_position").is_null()
)
どちらかの順位がnullだと差分もnullになる

そのため、まずは「previous_position(比較順位)」と「current_position(対象順位)」にfill_null()を使って、nullを101で埋めていきます。

df = df.with_columns(
    previous_position = pl.col("previous_position").fill_null(101),
    current_position = pl.col("current_position").fill_null(101),
)

これで圏外だった行には101が指定されたので、あとはprevious_positionとcurrent_positionの差分を、with_columnsを使ってposition_changeに入れます。
2つのカラムの値の差分を計算するには、カラムを指定するExprをマイナスで繋げるだけでOKです。

df = df.with_columns(
    position_change = pl.col("previous_position") - pl.col("current_position")
)
nullがなくなり、position_changeもInt64になった


また解説する都合上、上記のようにコードを分けて記載していますが、Polarsでは以下のようにメソッドを繋げて記載することも可能です。

df = df.with_columns(
    previous_position = pl.col("previous_position").fill_null(101),
    current_position = pl.col("current_position").fill_null(101),
).with_columns(
    position_change = pl.col("previous_position") - pl.col("current_position")
)

注意点としては、fill_nullを行っているwith_columnsと、position_changeを計算するためのwith_columnsは分けて記載する必要があることです

以下のようにひとつのwith_columns内で記載してしまうと、fill_nullを行う前の順位(つまりnullを含んでいる状態)でposition_changeが計算されるので、position_changeのカラムにはnullが入ってしまいます。

# ひとつのwith_columnsでposition_changeも計算すると、nullが入ってしまう
# fill_null実行前の値から計算されてしまうため
df = df.with_columns(
    previous_position = pl.col("previous_position").fill_null(101),
    current_position = pl.col("current_position").fill_null(101),
    position_change = pl.col("previous_position") - pl.col("current_position")
)


まとめ

nullと数値の差分を計算では計算結果がnullになってしまうため、計算前にnullを埋めるなどの対応が必要です。

またwith_columnsを使ってなにかしらの処理を行った値を使って、別の処理を行いたい場合には、with_columnsを分けて記載する必要があるようです。


この記事が気に入ったらサポートをしてみませんか?