NTT DATA TECH
⌨️

技術ブログの書き方 - 好きな技術を紹介する

に公開

ブログ執筆者倍増計画

NTT DATAでは、2025年4月からZennでの技術ブログを始めました。
これまでに約140記事が投稿され、比較的盛り上がっていると思うのですが、もっと執筆者を増やしたいけどどうしたらいいかなと広報部の方から聞かれたりしています。

「なんで俺に聞くねん」と思ったりもしたのですが、一説によると、技術ブログを始めることになったきっかけは私が社長に言った一言だったらしく、私は知らない間にブロガーとして認知されていたようでした。

そこで、 さすがに責任の一端を感じ、 せっかく自由にブログを書ける環境を整えてもらったので、技術ブログを書いたことがない人に向けて「好きな技術を紹介する」というテーマで記事を書く方法をアドバイスしようと思います。もちろん、書き方は他にもいろいろありますので、あくまで一例として、使えるところがあれば使ってやる程度の気持ちで読んでください。

技術ブログの書き方

とりあえず、こんな感じで書くと綺麗にまとまるかなと思います。繰り返しになりますが、あくまで一例ですので、この通りにしないといけないとかではなく、いいなと思った部分は真似してもらえればと思います。

技術ブログで目指すこと

技術ブログの目的は、読者に技術的な知識を授けることです。
つまり、技術ブログを書く人は、想定読者が誰で、伝える知識が何であるか、を明確に分かっている必要があります。そして、狙い通りに読者に知識を届けられるように記事を書きます。

まずは想定読者を考えましょう。よく、説明文を書くときは、中学生でも分かるようにとか、自分の両親でも分かるようにとか言われます。けれども、技術ブログではそこまでは想定読者を広く取る必要はありません。ある程度の専門性と前提知識を持った想定読者を考えても構いません。
一方で、想定読者があまりにも狭いと、読んでもらえる範囲は少なくなります。また、高度な専門性を有する読者を想定すると、著者にも相応の高度な専門性が期待されハードルが上がります。なので、想定読者は、ある程度は広めに設定することをおすすめします。

続いて、伝える知識が何であるかを考えましょう。
今回は「好きな技術を紹介する」というネタで行くことにします。ここで「私は、◯◯が好きです」という情報を伝えても、それは技術的な知識とは言えません。なぜそれが好きなのかを、技術的な知識と言えるくらいまで解像度を上げて言語化します。
もしかしたら、言語化している段階で、はじめて気づく「好き」が見つかるかもしれません。アウトプットの魅力のひとつは、アウトプットする対象に改めて別の視点で向き合えることです。

そして、元々何を知っていて何を知らない読者が、この記事を読んだら、どういう順番で何を知って、最終的に何が得られるのか、ざっくりとした流れを考えます。

技術ブログの構造

文章は構造を意識すると、いい感じに書けます。そのときは、よく使われている構造を流用するのがおすすめです。文章にもプログラムのように、デザインパターンがあるということですかね。

技術的な文章で、よく使われている構造といえば、大学のレポートや論文の構造です。一方で、技術ブログは位置づけとしてはもう少しゆるいものですので、これをベースにちょっとゆるくしていきましょう。

分野によって若干の違いがありますが、理工学系の論文は概ね次のような構造になっています。

タイトル

概要 (Abstract)

論文が示したものは何か、どのような位置づけか、どのような価値があるか、
どのような結論が得られたかを短文で示します。

導入 (Introduction)

なぜこのテーマに取り組むのか、どのような問題意識を持っていたのかが説明されています。
例えば、「既存の方法では〇〇という課題があり、より効率的な□□が求められていた」など。

方法 (Method)

課題にどのようにアプローチしたのか、技術的な詳細が説明されています。

結果 (Result)

実際に取り組んだ結果を説明されています。

考察 (Discussion)

結果をどう解釈するか、どのような意味があるのかを論じます。
うまくいった点だけでなく、課題や今後の改善点にも触れられています。

まとめ (Conclusion)

論文の要点を簡潔にまとめられています。

参考文献 (References)

  • 参考にした論文や書籍

ここから、例えば次のような形に構造化します。見出しの名前は、いい感じに変えてしまって問題ありません。

# はじめに
最初の掴みの部分です。この記事を書こうと思ったきっかけ、何が書かれているのか、
想定読者がどういった人で、読んだら何が得られるかを書きます。

やや、読者の興味を引くような感じに工夫しましょう。
書こうとしている技術が見せる大きなビジョン、最近流行っているキーワード、
世間でよく知られた言葉などを入れるといいかもしれません。
ちょっとした小ネタを挟んでもいいですが、スベっても大丈夫な程度に抑えておきましょう。
分量は、あんまり長すぎない方がいいです。

# 基礎となる知識
想定読者がこの先の記事を読んで、意味が理解できるように、必要な基礎知識を導入します。
想定読者が当然知っているはずのことは書かなくてもいいのですが、
知っているはずのことから始めて、ウォーミングアップしていくのも有効です。

例えば、

- 紹介したい技術の概要 (まずは「何?」とかそういうレベル。詳細は後に回す)
- 読者がおそらく使っているであろう類似の技術
- 紹介したい技術について理解する上で必要となること
- 記事内で使う独自の用語や概念、指標など

など、知っておいてほしいことをここで書きます。
多くなる場合は `## 見出し` で、さらに見出しを区切って書いても構いません。

# (紹介したい技術)の解説や使い方
技術ブログでは、ここが本編のようなものです。紹介したい技術を思う存分解説します。

使い方を紹介する場合は、環境構築の手順、使用した技術スタック、設計思想、
工夫した点、実装上のポイントなどを具体的に書きます。
必要に応じてコード例や図を挿入します。

# やってみた結果
紹介したい技術を動かしてみた結果や、得られた結果を紹介します。
また、考察や今後の課題も書きます。技術ブログの場合は、割と感想に近い感じでも許されます。

# まとめ
背景や方法と結果を振り返りながら全体をまとめます。
この記事で読者が得られたことや、自分が伝えたかったことを手短にまとめます。

# 参考文献
学術論文ではないので、そこまでたくさん文献を載せる必要はありませんが、
記事を書く上で参考にした主要な文献、興味がある読者にぜひ読んでほしい文献を掲載します
(他のブログ記事、公式ドキュメント、GitHubレポジトリへのリンクなど)。

試しに書いてみる

そう言われても分からん、と思います。なので、実際にやってみましょう。
例えば、データ分析に広く使われるPythonライブラリ「Pandas」の代替となる、「Polars」ライブラリが個人的にすごく好きで、みなさんに良さを知ってほしいと思っています。

そこで、以下のように想定読者、伝える知識、流れを考えます。

  • 想定読者: Pandasでデータ分析を行ったことがあるエンジニア
  • 伝える知識:
    • Polarsは、高速なDataFrameライブラリで、Pandasの代替となりうる
    • Polarsは宣言的なAPI設計で、部分的にデータを書き替えるのではなく操作方法を記述する
      • ソースコードが複雑化しにくい
      • データの書き換えを原因とするバグに遭遇しにくい
      • 考え方に慣れたらPandasよりも書きやすい
    • (余裕があれば触れる) Polarsは遅延評価可能なLazyFrameを用意しており、計算が必要なタイミングで必要な箇所のみを計算でき、処理によっては通常のDataFrameよりも大幅に高速 ⇒記事が長くなるので今回は省略することにしました
  • 流れ: 読者は、Pandasの悩みについて共感しながら、Polarsの存在やその書き方を知り、また実際に動かした結果が高速であることを理解する

これを、構造に沿って、以下のような感じの記事にします。

Polarsを使った高速で宣言的なデータ分析

データ分析や前処理の現場で、Pythonユーザーの多くが頼りにしているのがPandasです。私も長年お世話になってきましたが、最近「Polars」という新しいライブラリを使ってみたところ、高速で書きやすく、ものすごく好きになりました。

Polarsって何?

PolarsはPython向けの高速なデータフレームライブラリです。Pythonで使えるデータフレームライブラリとしてはPandasが広く使われていますが、Pandasと比べて以下のような特徴があります。

非破壊的で宣言的なAPI設計: セルやスライスを直接操作しなくても、列に対する操作を記述することができます。また、元のDataFrameを変更せずにDataFrameの操作ができるため、バグが入り込みにくいです。
高速な処理や遅延評価: 内部の実装がRustで書かれていて、Pandasと比べて高速です。また、遅延評価であるLazyFrameを用いると、必要な部分のみが必要なタイミングで計算がされるため、場合によっては更なる高速化が期待できます。

これらの特徴により、Pandasではとてもゴタゴタとしてしまっていたソースコードがシンプルでメンテナンスしやすくなったり、時間がかかっていた処理が高速化するなどの恩恵を得ることができます。

書き比べてみる

実際に、PandasとPolarsで同じ処理を書いてみましょう。
今回は、Irisデータセットを例に、DataFrameに、ガクの長さに関する列、花弁の面積に関する列を追加してみます。

インストール

pipuv で必要なパッケージをインストールします。

uv add pandas polars sklearn
または
uv pip install pandas polars sklearn
または
pip install pandas polars sklearn

Pandasの場合

import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris(as_frame=True)
df = iris.frame

# ガクの長さが平均以上かどうかのフラグ列を作る
df["is_long"] = df["sepal length (cm)"] > df["sepal length (cm)"].mean()

# 花弁の面積(長さx幅)が2以上のもののみ取り出す
df["petal area"] = df["petal length (cm)"] * df["petal width (cm)"]
filtered = df[df["petal area"] > 2.0]

よくある見慣れたPandasのコードですが、dfを書き換える処理を多用するので、Jupyter Notebookでのセルの再実行でエラーが起こりがちです。
また、 df[df["petal area"] > 2.0]の部分は、dfの名前を変更したときに名前の変更を忘れがちでバグを埋め込みやすいです。

Polarsの場合

import polars as pl
from sklearn.datasets import load_iris

iris = load_iris(as_frame=True)
# DataFrameを作る
df = pl.DataFrame(iris.frame)

filtered = df.with_columns(  # `DataFrame.with_columns(...)` で、列を追加する
        # `pl.col(...)` で列を選択し、列に対する計算式を作り指定する
        (pl.col("sepal length (cm)") > pl.col("sepal length (cm)").mean()).alias("is_long"),
        (pl.col("petal length (cm)") * pl.col("petal width (cm)")).alias("petal area")
    ).filter(                # `DataFrame.filter(...)` で、フィルター条件を指定する
        pl.col("petal area") > 2.0
    )

Polarsでは、DataFrameそのものは変更せずに、新たなDataFrameを作りながら処理を進めます。別名でDataFrameを作っておけばセルの再実行でバグが起こりにくく、また、別名を作りたくない場合は df = df.with_columns(...) のようにも書けます。新たなDataFrameを作っても、無駄なデータの複製は避けるようPolarsが管理してくれており軽量です。

性能比較

性能比較のため、Irisデータセットを10万倍のデータサイズに拡張し、時間を測定してみます。

import time
from sklearn.datasets import load_iris
import pandas as pd
import polars as pl

# Irisデータセットを読み込み
iris = load_iris(as_frame=True)
df_base = iris.frame

# 10万倍に拡張
repeat = 100_000
pandas_df = pd.concat([df_base]*repeat, ignore_index=True, copy=True)
polars_df = pl.concat([pl.DataFrame(df_base)]*repeat, rechunk=True)

# Pandas
start = time.time()
# 平均値を基準にフラグ列を追加
pandas_df["is_long"] = pandas_df["sepal length (cm)"] > pandas_df["sepal length (cm)"].mean()
# 列を変換してフィルタ
pandas_df["petal area"] = pandas_df["petal length (cm)"] * pandas_df["petal width (cm)"]
filtered_pandas = pandas_df[pandas_df["petal area"] > 2.0]
pandas_time = time.time() - start

# Polars
start = time.time()
result_polars = polars_df.with_columns(
        (pl.col("sepal length (cm)") > pl.col("sepal length (cm)").mean()).alias("is_long"),
        (pl.col("petal length (cm)") * pl.col("petal width (cm)")).alias("petal area")
    ).filter(pl.col("petal area") > 2.0)
polars_time = time.time() - start

print(f"結果が同じであるか: {pl.from_pandas(filtered_pandas).equals(result_polars)}")
print(f"Pandas処理時間: {pandas_time:.3f}秒")
print(f"Polars処理時間: {polars_time:.3f}秒")

すると、私の環境では、

結果が同じであるか: True
Pandas処理時間: 0.514秒
Polars処理時間: 0.210秒

が得られました!
こんなに単純な処理でも、Polarsの方が2倍以上高速化していました。
また、コードの見た目としても、少し慣れが必要ですが、DataFrameの変更や df[df["列名"] > 2.0] のような記述が出てこなくなり、メンテナンス性が高くなりました。

まとめ

Polarsは高速で、メンテナンス性の高い書き方のできるDataFrameライブラリです。
一度使うと良さが分かりますので、騙されたと思って一度使ってみてください!

参考文献

これくらいなら書けそうって気持ちになってきませんか?

技術ブログはいいぞ

好きなことがあって、それを発信できるというのは幸せなことです。
そうすることで、面白いと思うもの、好きだと思うものをもっと好きになれるかもしれないですし、同じようにそれを好きな人とつながるきっかけになるかもしれないです。
また、読者がブログを読んで、それを好きになってくれることだってあるかもしれません。

なので、みなさんも是非、自分の好きな技術を発信してください!

NTT DATA TECH
NTT DATA TECH
設定によりコメント欄が無効化されています