はじめに:「エリアによって使われる言語って違うの?」という素朴な疑問
ある日、弊社のデータエンジニアがこんなことを言い出しました。
「日本のエンジニアってPythonとJavaどっちが好きなんだろう。インドはどうなんだろう。あと他の国のエンジニアは実際どうなの?」
そこで BigQuery の一般公開データセット、すなわち Stack Overflow のユーザーデータ に手を伸ばしました。Stack Overflow は世界中の開発者が日々「助けてくれ〜」「なんでこんなエラー出るんじゃ〜」と叫ぶ場所です。そこに世界の開発者文化の縮図があります。(たぶん)

結果:各エリアの「推し言語」事情がおもしろい
実際にビジュアライズしてみた結果を、エリア別に見ていきましょう。
🗾 Japan(日本)

- 「JavaScriptとPythonが最強タッグ?!」
どうやら日本のエンジニアは、フロントエンドもバックエンドもデータ分析も、何でもござれなフルスタック志向が強いようです。JavaScriptとPythonの両方を操るプログラマーが多いのは、まさに現代の開発現場のトレンドを反映していますね。 - JavaとSQLは「縁の下の力持ち」
大きな円で存在感を示すJavaと、複数の言語と重なり合うSQLは、日本のITインフラを支える大黒柱といったところでしょうか。派手さはないけれど、彼らがいないとシステムが成り立たない、まるで日本の伝統工芸品の職人のようです。 - R言語は「孤高のデータサイエンティスト」の証
Pythonとの重複はありますが、R単独の領域があるのは、特定の分野で深くRを使いこなす専門家がいることを示唆しています。彼らは流行に流されず、ひたすらデータと向き合う求道者なのかもしれませんね!
🇬🇧 United Kingdom(イギリス)

- SQLはイギリスの隠れた主役?!
JavaScriptやPythonが華々しく活躍する一方で、SQLが単独でも大きな存在感を放ち、さらに多くの言語と絡み合っているのが印象的です。もしかしたら、イギリスのエンジニアは「データはすべてを語る」という哲学のもと、データベースとの対話を何よりも重視しているのかもしれませんね! - Javaは「堅実な老舗」、JavaScriptとPythonは「新進気鋭の若手」
Javaが単独で大きな円を描いているのは、伝統的なエンタープライズ領域でその堅牢さが重宝されている証拠でしょう。一方で、JavaScriptとPythonは、SQLと手を組みながら新しい技術トレンドを追いかけている、そんな対比が見えてきます。 - PythonとR、そしてSQLのトライアングル!
データサイエンスの領域では、PythonとRが手を組み、さらにSQLと密接に連携していることが伺えます。これは、データ収集から分析、そして活用までを一貫して行う、高度なデータ駆動型アプローチがイギリスで進んでいることを示唆しているようですね!
🇮🇳 India(インド)

- Javaの威風堂々たる存在感!
インドではJavaが圧倒的な「キング」の座を占めているようです。広大な面積を持つその円は、まるでインドの雄大な大地そのもの。企業の基幹システムから大規模開発まで、Javaが国のITインフラを根底から支えている様子が目に浮かびますね。 - JavaScriptとPython、そしてJavaの三つ巴?!
JavaScript、Pythonがそれぞれ大きな勢力を持つ中で、この3言語が複雑に絡み合う中心領域は、まさにインドの開発者の「マルチリンガル」っぷりを象徴しています。フロントエンドからバックエンド、データサイエンスまで、どんな要件にも対応できる「ITの万能選手」がインドにはゴロゴロいそうですね。 - R言語は「孤高のデータ分析マスター」のツール?
どの国でもニッチな存在になりがちなRですが、インドではSQLとわずかに接点を持つものの、ほとんど独立した小さな円として存在しています。これは、大量のデータを扱う専門的な分析分野で、Rを深く使いこなすプロフェッショナルが着実に活躍している証拠かもしれません。彼らは流行に左右されず、ひたすら数字と格闘する真の求道者なのでしょう。
まとめ
Stack OverflowのデータをBigQueryで集計し、LookerのVenn Diagramで可視化することで、**「世界の開発者たちのプログラミング言語愛好傾向」**が見える結果となりました。みなさんの推し言語はどこに分布していましたか?いろいろな推し言語を身につけて成長していきましょう!
おまけ
-
今回検証に用いた公開データセットとSQL
bigquery-public-data.stackoverflow.usersbigquery-public-data.stackoverflow.posts_questionsWITH user_languages AS ( SELECT u.location AS raw_location, u.id AS userid, MAX( CASE WHEN REGEXP_CONTAINS(p.tags, r'(?i)\\bpython\\b') THEN 'Python' END) AS lang_python, MAX( CASE WHEN REGEXP_CONTAINS(p.tags, r'(?i)\\bjavascript\\b') THEN 'JavaScript' END) AS lang_js, MAX( CASE WHEN REGEXP_CONTAINS(p.tags, r'(?i)\\bjava\\b') THEN 'Java' END) AS lang_java, -- ▼ Rの誤検知防止: タグ全体が"r"のみ、または"|r|"区切り MAX( CASE WHEN REGEXP_CONTAINS(p.tags, r'(?i)(^|\\|)r(\\||$)') THEN 'R' END) AS lang_r, MAX( CASE WHEN REGEXP_CONTAINS(p.tags, r'(?i)\\bsql\\b') THEN 'SQL' END) AS lang_sql FROM `bigquery-public-data.stackoverflow.users` u JOIN `bigquery-public-data.stackoverflow.posts_questions` p ON u.id = p.owner_user_id -- ▼ GROUP BYでuserid単位に集約(重複排除) GROUP BY u.location, u.id ), aggregated AS ( SELECT userid, raw_location, -- ▼ NULL除外・重複排除・ソートして|結合 ARRAY_TO_STRING( ARRAY( SELECT DISTINCT lang FROM UNNEST( [ lang_python, lang_js, lang_java, lang_r, lang_sql]) AS lang WHERE lang IS NOT NULL ORDER BY lang ), '|') AS language FROM user_languages ), area_inferred AS ( SELECT userid, language, CASE WHEN REGEXP_CONTAINS( LOWER(raw_location), r'japan|tokyo|osaka|kyoto|sapporo') THEN 'Japan' WHEN REGEXP_CONTAINS( LOWER(raw_location), r'india|mumbai|delhi|bangalore|chennai|hyderabad') THEN 'India' WHEN REGEXP_CONTAINS( LOWER(raw_location), r'united states|usa|u\\.s\\.a|new york|california|texas|seattle|chicago') THEN 'United States' WHEN REGEXP_CONTAINS( LOWER(raw_location), r'united kingdom|uk|u\\.k\\.|london|england|scotland|wales') THEN 'United Kingdom' WHEN REGEXP_CONTAINS( LOWER(raw_location), r'germany|deutschland|berlin|munich|hamburg') THEN 'Germany' WHEN REGEXP_CONTAINS(LOWER(raw_location), r'france|paris|lyon|marseille') THEN 'France' WHEN REGEXP_CONTAINS( LOWER(raw_location), r'china|beijing|shanghai|shenzhen|guangzhou') THEN 'China' WHEN REGEXP_CONTAINS( LOWER(raw_location), r'brazil|brasil|são paulo|rio de janeiro|brasilia') THEN 'Brazil' WHEN REGEXP_CONTAINS( LOWER(raw_location), r'canada|toronto|vancouver|montreal|ottawa') THEN 'Canada' WHEN REGEXP_CONTAINS( LOWER(raw_location), r'australia|sydney|melbourne|brisbane|perth') THEN 'Australia' WHEN REGEXP_CONTAINS( LOWER(raw_location), r'netherlands|amsterdam|rotterdam') THEN 'Netherlands' WHEN REGEXP_CONTAINS(LOWER(raw_location), r'sweden|stockholm|gothenburg') THEN 'Sweden' WHEN REGEXP_CONTAINS(LOWER(raw_location), r'poland|warsaw|krakow') THEN 'Poland' WHEN raw_location IS NULL OR TRIM(raw_location) = '' THEN 'Unknown' ELSE 'Other' END AS area FROM aggregated -- ▼ 言語が1つも特定できなかったレコードを除外 WHERE language != '' ) SELECT area, userid, language FROM area_inferred ORDER BY area, userid;