strアクセサとは、文字列が格納されたSeriesやIndexで使える機能です。strアクセサを介することで、「文字数をカウントする」「指定した文字列を置換する」といった文字列処理でよくある操作を簡潔に記述できます。
具体的な例を見てみましょう。次のような口コミのデータについて考えてみます。
ユーザーID | 評価 | コメント | |
---|---|---|---|
0 | user1 | 5 | とても使いやすく書きやすいです!2本目を買いたいと思います! |
1 | user2 | 3 | 改善の余地あり。使い始めは良かったが、だんだんインクがかすれやすくなりました。 |
2 | user3 | 2 | 左利きの私が使うとインクが上手く出てこないようです。残念です。 |
3 | user4 | 4 | 概ね満足しています。書きやすく長く持ちます。リーズナブルな価格も良いです。 |
各行のコメント
の文字数をカウントする場合、前クエスト「列や行に関数を適用しよう」で学んだapply()
を使って次のように書けます。
def calc_length(comment):
# 列「コメント」の文字数を求める
return len(comment)
df["コメント"].apply(calc_length)
0 30
1 39
2 31
3 37
Name: コメント, dtype: int64
これは、strアクセサを使うと次のように簡潔に記述できます。
# strアクセサを使って列「コメント」の文字数を求める
df["コメント"].str.len()
strアクセサでは、NaNを考慮して処理を行う点も便利です。たとえば次のようなNaNを含むデータの場合について考えてみましょう。
ユーザーID | 評価 | コメント | |
---|---|---|---|
0 | user5 | 5 | NaN |
1 | user6 | 5 | 前から使っていますが、リニューアル後はインクが改善されたように思います。 |
apply()
で関数を適用する場合、NaNを考慮して処理を書かないとTypeErrorが発生する可能性があります。
しかしstrアクセサを使うと、NaNを考慮して処理されます。
# strアクセサを使って列「コメント」の文字数を求める
df["コメント"].str.len()
0 NaN
1 36.0
Name: コメント, dtype: float64
pandasのstrアクセサでは、Pythonの組み込み型のstrで使える関数やメソッドに似た名前の機能が使えます。正規表現に対応しているなど、組み込み型のstrで使える同名のメソッドよりも機能が増えているものもあります。
以下に、よく使われるものを挙げます。
メソッドなど | 説明 |
---|---|
str.len() | 文字数を数える |
str.count(対象文字列) | 指定した文字列の出現回数を数える |
str.lower() | 小文字に変換する |
str.upper() | 大文字に変換する |
str.strip(除去する文字) | 指定した文字が先端と終端にある場合除去する |
str.replace(置換前の文字列, 置換後の文字列) | 指定した文字列を置換する。正規表現も使用可能 |
str.contains(対象文字列) | 指定した文字列が含まれるかどうか判定する |
str.match(正規表現のパターン) | 正規表現で検索する |
str.startswith(対象文字列) | 指定した文字列で開始するかどうか判定する |
str[インデックス] | 指定したインデックスの位置の文字を取得する |
str[開始位置:終了位置] | スライス機能。開始位置から終了位置までの範囲の部分文字列を取得する |
演習
- 列
コメント
内の文字の置換: 各行の列コメント
内の全角の感嘆符(!
)を句点(。
)に変換 - 列
文字数
の追加: 各行の列コメント
の文字数 - 列
インク
の追加: 各行の列コメント
内に"インク"
が含まれているかどうか(True/False) - 列
スライス
の追加: 各行の列コメント
の先頭15文字を抽出した結果
import pandas as pd
# 口コミデータの読み込み
df = pd.read_csv("dataset/rating.csv")
df
ユーザーID | 評価 | コメント | |
---|---|---|---|
0 | user1 | 5 | とても使いやすく書きやすいです!2本目を買いたいと思います! |
1 | user2 | 3 | 改善の余地あり。使い始めは良かったが、だんだんインクがかすれやすくなりました。 |
2 | user3 | 2 | 左利きの私が使うとインクが上手く出てこないようです。残念です。 |
3 | user4 | 4 | 概ね満足しています。書きやすく長く持ちます。リーズナブルな価格も良いです。 |
4 | user5 | 5 | NaN |
5 | user6 | 5 | 前から使っていますが、リニューアル後はインクが改善されたように思います。 |
次に、列コメント
からを全角の感嘆符(”!”)を句点(”。”)で置換しましょう。str.replace(置換前の文字列, 置換後の文字列)
で置換できます。
# 全角の!を。に置換
df["コメント"] = df["コメント"].str.replace("!", "。")
実行結果を見ると、1行目にあった”!”が意図通り置換されていることがわかります。また、元々NaN
だったuser5のコメントはNaN
のままであることがわかります。
# 実行結果の確認
df
ユーザーID | 評価 | コメント | |
---|---|---|---|
0 | user1 | 5 | とても使いやすく書きやすいです。2本目を買いたいと思います。 |
1 | user2 | 3 | 改善の余地あり。使い始めは良かったが、だんだんインクがかすれやすくなりました。 |
2 | user3 | 2 | 左利きの私が使うとインクが上手く出てこないようです。残念です。 |
3 | user4 | 4 | 概ね満足しています。書きやすく長く持ちます。リーズナブルな価格も良いです。 |
4 | user5 | 5 | NaN |
5 | user6 | 5 | 前から使っていますが、リニューアル後はインクが改善されたように思います。 |
strアクセサを使って、コメントの文字数を数えてみましょう。df[列名].str.len()
とすることで、指定した列の文字数を数えられます。
# 列コメントの文字数を数える
df["文字数"] = df["コメント"].str.len()
df
ユーザーID | 評価 | コメント | 文字数 | |
---|---|---|---|---|
0 | user1 | 5 | とても使いやすく書きやすいです。2本目を買いたいと思います。 | 30.0 |
1 | user2 | 3 | 改善の余地あり。使い始めは良かったが、だんだんインクがかすれやすくなりました。 | 39.0 |
2 | user3 | 2 | 左利きの私が使うとインクが上手く出てこないようです。残念です。 | 31.0 |
3 | user4 | 4 | 概ね満足しています。書きやすく長く持ちます。リーズナブルな価格も良いです。 | 37.0 |
4 | user5 | 5 | NaN | NaN |
5 | user6 | 5 | 前から使っていますが、リニューアル後はインクが改善されたように思います。 | 36.0 |
次に、列コメント
に”インク”という文字列が含まれているか調べてみましょう。 str.contains(対象文字列)
とすることで、指定した文字列が含まれるか判定できます。
# "インク"を含むか判定
df["インク"] = df["コメント"].str.contains("インク")
df
ユーザーID | 評価 | コメント | 文字数 | インク | |
---|---|---|---|---|---|
0 | user1 | 5 | とても使いやすく書きやすいです。2本目を買いたいと思います。 | 30.0 | False |
1 | user2 | 3 | 改善の余地あり。使い始めは良かったが、だんだんインクがかすれやすくなりました。 | 39.0 | True |
2 | user3 | 2 | 左利きの私が使うとインクが上手く出てこないようです。残念です。 | 31.0 | True |
3 | user4 | 4 | 概ね満足しています。書きやすく長く持ちます。リーズナブルな価格も良いです。 | 37.0 | False |
4 | user5 | 5 | NaN | NaN | NaN |
5 | user6 | 5 | 前から使っていますが、リニューアル後はインクが改善されたように思います。 | 36.0 | True |
str.contains()
はTrue/Falseを返すため、データの絞り込みでもよく使われます。
最後に、列コメント
を15文字目までスライスしてみましょう。strアクセサでは、Pythonのstrと同様スライス機能が使えます。
# 列コメントの先頭15文字を抽出する
df["スライス"] = df["コメント"].str[:15]
df
ユーザーID | 評価 | コメント | 文字数 | インク | スライス | |
---|---|---|---|---|---|---|
0 | user1 | 5 | とても使いやすく書きやすいです。2本目を買いたいと思います。 | 30.0 | False | とても使いやすく書きやすいです |
1 | user2 | 3 | 改善の余地あり。使い始めは良かったが、だんだんインクがかすれやすくなりました。 | 39.0 | True | 改善の余地あり。使い始めは良か |
2 | user3 | 2 | 左利きの私が使うとインクが上手く出てこないようです。残念です。 | 31.0 | True | 左利きの私が使うとインクが上手 |
3 | user4 | 4 | 概ね満足しています。書きやすく長く持ちます。リーズナブルな価格も良いです。 | 37.0 | False | 概ね満足しています。書きやすく |
4 | user5 | 5 | NaN | NaN | NaN | NaN |
5 | user6 | 5 | 前から使っていますが、リニューアル後はインクが改善されたように思います。 | 36.0 | True | 前から使っていますが、リニュー |
コメント