Sosyal Medya Verileriyle Marka Karşılaştırması

“Hangi marka daha iyi?” ölçülebilir bir soru değil. Hacim, etkileşim oranı, duygu dağılımı ve konuşulma payını aynı kapsamda nasıl ölçeceğinizi ve her birinin neyi söyleyip neyi söylemediğini anlatıyorum.

  • Sosyal Medya

Karşılaştırma neyi yanıtlamalı?

“Hangi marka daha iyi?” tek başına ölçülebilir bir soru değildir. Daha çok mu konuşuluyor, daha yüksek etkileşim mi alıyor, yoksa konuşmalarındaki ton mu daha olumlu? Bu üç soru farklı metrikler, farklı paydalar ve farklı yorumlar gerektirir.

Karşılaştırma için aynı tarih aralığını, benzer platform kapsamını ve tutarlı marka sorgularını kullanın. Marka isminin yaygın bir kelimeyle çakışması, aynı adı taşıyan başka ürünler veya kullanıcı adları sonucu kirletir; sorgularınızı mutlaka örnek paylaşımlar üzerinden doğrulayın.

Adil başlangıç: iki marka, aynı dönem, aynı platform kapsamı ve açıkça tanımlanmış ölçütler. Sonuçları hedef kitle, kampanya takvimi ve platform farklarıyla birlikte yorumlayın — aksi hâlde ölçtüğünüz şey marka performansı değil, ölçüm kurulumunuz olur.

1. Veriyi hazırlayın

Her paylaşım için marka, platform, zaman, metin, etkileşim sayıları ve mümkünse erişim/gösterim alanları tutarlı biçimde saklanmalı. Tekilleştirme, dil tespiti, spam filtresi ve yeniden paylaşımların nasıl ele alınacağı gibi kuralları en baştan belirleyin.

CSV yükleme ve temel hazırlık
import pandas as pd

df = pd.read_csv("veri/sosyal_paylasimlar.csv", parse_dates=["tarih"])

df["marka"] = df["marka"].str.strip().str.casefold()
df["etkilesim"] = df[["begeni", "yorum", "paylasim"]].fillna(0).sum(axis=1)
df["gun"] = df["tarih"].dt.date

print(df.groupby("marka").size())
print(df[["platform", "tarih", "marka"]].isna().sum())

casefold(), lower()'dan biraz daha agresif bir normalleştirme yapar (örneğin Almanca ß'yi ss'ye çevirir) ve karşılaştırma amaçlı eşleştirmede tercih edilir. Ama dikkat: ikisi de yerel ayara duyarlı değildir. Python'da "I".casefold() sonucu "i"dir, Türkçedeki "ı" değil. Marka adlarında Türkçe büyük/küçük harf farkı önemliyse bunu ayrıca ele almanız gerekir. Beğeni, yorum ve paylaşımı tek bir etkileşim puanında toplarken de ağırlıklarının eşit olduğunu varsaydığınızı unutmayın; farklı ağırlık kullanıyorsanız formülü raporda açıkça yazın.

2. Paylaşım sayısı ve konuşulma hacmi

Markanın kendi paylaşım sayısı, ne kadar içerik yayımladığını gösterir. Konuşulma hacmi ise seçilen sorgu içinde markadan bahseden yakalanmış paylaşım sayısıdır. Bu ikisini ayrı raporlamak şart: markanın ürettiği gönderilerle kullanıcıların ürettiği konuşmalar tamamen farklı şeyler anlatır.

Marka ve gün bazında hacim
hacim = (df.groupby(["marka", "gun"])
           .size().rename("paylasim_sayisi").reset_index())

toplam = (df.groupby("marka")
            .agg(paylasim=("metin", "size"),
                 toplam_etkilesim=("etkilesim", "sum"))
            .sort_values("paylasim", ascending=False))
print(toplam)

Ham hacim; marka bilinirliği, kampanya harcaması, takipçi tabanı ve platform erişiminden etkilenir. Hacim artışı tek başına olumlu algı ya da başarı anlamına gelmez — olumsuz bir olay da konuşulma hacmini kolayca ikiye katlar.

3. Etkileşimi adil karşılaştırın

Toplam etkileşim, büyük takipçi kitlesi olan ya da daha sık paylaşım yapan markayı doğal olarak öne çıkarır. Mümkünse erişim veya takipçi başına oranları hesaplayın; paylaşım türünü ve platformu da ayrı değerlendirin.

Etkileşim oranı
# Erişim varsa: erişim başına etkileşim daha açıklayıcıdır
df["erisim_orani"] = df["etkilesim"] / df["erisim"].where(df["erisim"] > 0)

# Erişim yoksa takipçi sayısı yaklaşık payda olarak kullanılabilir
df["takipci_orani"] = df["etkilesim"] / df["takipci"].where(df["takipci"] > 0)

ozet = (df.groupby(["marka", "platform"])
          .agg(ortalama_erisim_orani=("erisim_orani", "mean"),
               ortanca_etkilesim=("etkilesim", "median"),
               paylasim=("etkilesim", "size")))
print(ozet.round(4))

where(... > 0) kullanımı sıfıra bölmeyi engeller ve o satırları NaN yapar; böylece oranlar sessizce sonsuza gitmez. Ortalama tek bir viral gönderiden ciddi biçimde etkilenebileceği için medyanı da birlikte raporlayın. Ve en önemlisi: erişim başına oran ile takipçi başına oran aynı şey değildir, ikisini aynı tabloda yan yana koymayın.

4. Duygu dağılımını yorumlayın

Duygu analizi metinleri çoğunlukla olumlu, nötr ve olumsuz sınıflara ayırır. Sınıflandırıcılar ironi, argo, emoji, bağlam, çok dilli kullanım ve marka adlarını yanlış okuyabilir. Skor, kamuoyunun kusursuz ölçümü değil, incelenmesi gereken yaklaşık bir göstergedir.

Duygu yüzdeleri
# duygu sütununun pozitif / nötr / negatif etiketleri içerdiğini varsayalım
duygu_sayisi = pd.crosstab(df["marka"], df["duygu"])
duygu_yuzde = pd.crosstab(df["marka"], df["duygu"], normalize="index") * 100

print(duygu_sayisi)
print(duygu_yuzde.round(1))

Yüzdeleri her zaman örnek sayısıyla birlikte paylaşın. 40 paylaşımda %70 olumlu ile 4.000 paylaşımda %70 olumlu aynı güvende değildir. Otomatik etiketlerin bir bölümünü elle gözden geçirin: hem model hatalarını görürsünüz hem de hangi konuların hangi tonu çektiğini anlarsınız.

Bağlam şart: olumsuz duygu yüksekliği bir sorun sinyali olabilir; ama konu, ironi, kullanıcı profili ve kampanya dönemi incelenmeden marka algısı hakkında kesin hüküm vermez. Bir markanın kendi kanalındaki yorumlarla bağımsız kanallardaki yorumların tonu da genelde birbirinden ayrışır.

5. Konuşulma payı ve zaman içindeki değişim

Paylaşımların aynı izleme kapsamından geldiği varsayımıyla konuşulma payı, markanın toplam marka konuşmaları içindeki hacim oranıdır. Pazar payı ya da satın alma tercihiyle karıştırılmamalıdır. Günlük veya haftalık seri ise kampanya ve kriz sıçramalarını görünür kılar.

Konuşulma payı ve günlük seri
marka_hacmi = df.groupby("marka").size()
konusulma_payi = marka_hacmi / marka_hacmi.sum() * 100
print(konusulma_payi.round(1))

gunluk = (df.groupby(["gun", "marka"]).size()
            .rename("hacim").reset_index())

Paydanın hangi markaları ve hangi paylaşımları kapsadığını mutlaka belirtin. Tek bir rakibin sorgudan çıkarılması bile tüm payları değiştirir. Botlar, kopyala-yapıştır tekrarlar ve tek bir viral gönderi de hacmi kolayca şişirir.

6. Görseller ve karşılaştırma tablosu

Önce ortak tarih aralığında hacim eğilimini, ardından platforma göre etkileşim oranını ve duygu dağılımını gösterin. Eksenleri, paydaları ve birimleri etiketleyin; ham sayılarla oranları asla aynı grafikte karıştırmayın.

Günlük hacim grafiği
import seaborn as sns
import matplotlib.pyplot as plt

sns.lineplot(data=gunluk, x="gun", y="hacim", hue="marka")
plt.title("Günlük marka konuşulma hacmi")
plt.xlabel("Tarih"); plt.ylabel("Paylaşım sayısı")
plt.xticks(rotation=30)
plt.tight_layout()
plt.savefig("cikti/gunluk_hacim.png", dpi=160)
plt.close()
ÖlçütNe anlatır?Yorum sınırı
Paylaşım sayısıYayımlanan içerik adediKalite ve erişim ölçmez
Etkileşim oranıErişim veya takipçiye göre tepkiPayda ve platform tanımı belirleyici
Duygu dağılımıMetinlerdeki sınıflandırılmış tonModel hatası ve bağlam etkisi
Konuşulma hacmiİzlenen sorguda marka bahsiBilinirlik veya başarıyla aynı değil
Konuşulma payıSeçilen markalar arasındaki hacim payıİzleme kapsamına çok duyarlı

7. Bulguyu karara dönüştürün

Beş adım
  1. Soruyu
    Sabitle
  2. Sorguyu
    Doğrula
  3. Ham ve Oranlı
    Ölçüler
  4. Değişimleri
    Bağlamlandır
  5. İhtiyatla
    İfade Et
  1. Soruyu ve dönemi sabitleyin: aynı platform kapsamı, aynı tarih aralığı.
  2. Veri sorgusunu doğrulayın: marka adı, yazım varyantları, spam ve tekrarlar.
  3. Ham ve normalize ölçüleri yan yana verin: hacim, oran ve örneklem büyüklüğü birlikte.
  4. Değişimleri bağlamlandırın: kampanya, ürün duyurusu, kriz ve platform algoritma değişiklikleri.
  5. Sonucu ihtiyatla ifade edin: gözlemi nedensel iddiadan ayırın.
Örnek sonuç dili: “İzlenen dönemde A markası daha yüksek konuşulma hacmine sahipti; B markasının erişim başına etkileşim oranı daha yüksekti. Duygu sınıfları otomatik etiketlendi ve bir örneklem elle kontrol edildi. Bu göstergeler satın alma tercihini tek başına ölçmez.” Bu cümlenin gücü, söylediği kadar söylemediğinden de gelir.

Kontrol listesi

1

Soru net mi?

Hangi metriğe göre karşılaştırdığınızı raporun başında yazın.

2

Kapsam eşit mi?

Tarih aralığı ve platform listesi iki marka için birebir aynı olmalı.

3

Sorgu doğrulandı mı?

Marka adı çakışmalarını örnek paylaşımlar üzerinden elle kontrol edin.

4

Spam kuralları

Bot, tekrar ve yeniden paylaşım kuralları önceden tanımlı ve yazılı olsun.

5

Payda gösterildi mi?

Her oranın paydası ve örnek sayısı tabloda görünmeli.

6

Sınırlar yazıldı mı?

Model hatası, örneklem yanlılığı ve kapsam kısıtları raporda yer alsın.

Tek bir lider tablosu yeterli değil

Sosyal medya marka karşılaştırması tek bir sıralamadan ibaret değildir. Hacim görünürlüğü, oranlar etkileşim kalitesini, duygu dağılımı ise metinlerdeki yaklaşık tonu gösterir. Üçü farklı soruları yanıtlar ve çoğu zaman farklı markayı öne çıkarır.

Birden çok ölçüyü aynı kapsamda, paydalarıyla ve bağlamıyla sunmak hem daha adil hem de karar verirken daha işe yarar bir değerlendirme sağlar. “A markası önde” cümlesi, hangi metrikte ve hangi kapsamda önde olduğu yazılmadığı sürece bir bulgu değildir.

What should the comparison answer?

“Which brand is better?” is not on its own a measurable question. Is one talked about more, does it get higher engagement, or is the tone of its conversations more positive? Those three questions need different metrics, different denominators and different readings.

Use the same date range, comparable platform coverage and consistent brand queries. A brand name clashing with a common word, other products sharing the name, or usernames will pollute the results; always validate your queries against sample posts.

A fair starting point: two brands, the same period, the same platform coverage and clearly defined metrics. Interpret the results alongside audience, campaign calendar and platform differences — otherwise what you are measuring is your measurement setup, not brand performance.

1. Prepare the data

For every post, store brand, platform, time, text, engagement counts and — where available — reach or impressions consistently. Decide the rules for deduplication, language detection, spam filtering and how reshares are handled before you start.

Loading the CSV and basic preparation
import pandas as pd

df = pd.read_csv("veri/sosyal_paylasimlar.csv", parse_dates=["tarih"])

df["marka"] = df["marka"].str.strip().str.casefold()
df["etkilesim"] = df[["begeni", "yorum", "paylasim"]].fillna(0).sum(axis=1)
df["gun"] = df["tarih"].dt.date

print(df.groupby("marka").size())
print(df[["platform", "tarih", "marka"]].isna().sum())

casefold() normalises a little more aggressively than lower() (it maps the German ß to ss, for instance) and is the better choice for caseless matching. But note: neither is locale-aware. In Python "I".casefold() returns "i", not the Turkish "ı". If Turkish case differences matter in your brand names, you have to handle that separately. Note too that summing likes, comments and shares into one engagement figure assumes they weigh the same; if you use different weights, state the formula in the report.

2. Post count and conversation volume

A brand's own post count shows how much content it published. Conversation volume is the number of captured posts mentioning the brand within your query. Report the two separately: content the brand produced and conversation users produced tell entirely different stories.

Volume by brand and day
hacim = (df.groupby(["marka", "gun"])
           .size().rename("paylasim_sayisi").reset_index())

toplam = (df.groupby("marka")
            .agg(paylasim=("metin", "size"),
                 toplam_etkilesim=("etkilesim", "sum"))
            .sort_values("paylasim", ascending=False))
print(toplam)

Raw volume is shaped by brand awareness, campaign spend, follower base and platform reach. A rise in volume does not by itself mean positive perception or success — a negative incident doubles conversation volume just as easily.

3. Compare engagement fairly

Total engagement naturally favours the brand with the larger follower base or the one that posts more often. Where you can, compute rates per reach or per follower, and assess post type and platform separately.

Engagement rate
# If reach is available, engagement per reach is more informative
df["erisim_orani"] = df["etkilesim"] / df["erisim"].where(df["erisim"] > 0)

# Without reach, follower count can serve as an approximate denominator
df["takipci_orani"] = df["etkilesim"] / df["takipci"].where(df["takipci"] > 0)

ozet = (df.groupby(["marka", "platform"])
          .agg(ortalama_erisim_orani=("erisim_orani", "mean"),
               ortanca_etkilesim=("etkilesim", "median"),
               paylasim=("etkilesim", "size")))
print(ozet.round(4))

where(... > 0) prevents division by zero by turning those rows into NaN, so rates do not quietly run to infinity. Report the median alongside the mean, since a single viral post can distort the average badly. And most importantly: engagement per reach and engagement per follower are not the same thing — never put them side by side in one table.

4. Interpret the sentiment split

Sentiment analysis usually sorts text into positive, neutral and negative. Classifiers misread irony, slang, emoji, context, multilingual usage and brand names. The score is not a flawless measure of public opinion but an approximate indicator that needs examining.

Sentiment percentages
# assuming the sentiment column holds positive / neutral / negative labels
duygu_sayisi = pd.crosstab(df["marka"], df["duygu"])
duygu_yuzde = pd.crosstab(df["marka"], df["duygu"], normalize="index") * 100

print(duygu_sayisi)
print(duygu_yuzde.round(1))

Always publish percentages together with the sample size. 70% positive across 40 posts does not carry the same confidence as 70% across 4,000. Review a portion of the automatic labels by hand: you will see both the model's errors and which topics attract which tone.

Context is essential: a high share of negative sentiment can be a warning sign, but without examining topic, irony, user profile and campaign timing it settles nothing about brand perception. The tone of comments on a brand's own channel also tends to diverge sharply from those on independent channels.

5. Share of voice and change over time

Assuming all posts come from the same monitoring scope, share of voice is a brand's share of total brand conversation by volume. It must not be confused with market share or purchase preference. A daily or weekly series makes campaign and crisis spikes visible.

Share of voice and the daily series
marka_hacmi = df.groupby("marka").size()
konusulma_payi = marka_hacmi / marka_hacmi.sum() * 100
print(konusulma_payi.round(1))

gunluk = (df.groupby(["gun", "marka"]).size()
            .rename("hacim").reset_index())

State exactly which brands and which posts the denominator covers. Removing a single competitor from the query changes every share. Bots, copy-paste repetition and one viral post inflate volume just as easily.

6. Charts and a comparison table

Show the volume trend over the shared date range first, then the engagement rate by platform and the sentiment split. Label axes, denominators and units; never mix raw counts and rates in the same chart.

A daily volume chart
import seaborn as sns
import matplotlib.pyplot as plt

sns.lineplot(data=gunluk, x="gun", y="hacim", hue="marka")
plt.title("Daily brand conversation volume")
plt.xlabel("Date"); plt.ylabel("Posts")
plt.xticks(rotation=30)
plt.tight_layout()
plt.savefig("cikti/gunluk_hacim.png", dpi=160)
plt.close()
MetricWhat it showsLimit of interpretation
Post countVolume of content publishedMeasures neither quality nor reach
Engagement rateResponse relative to reach or followersDenominator and platform definition decide it
Sentiment splitClassified tone in the textModel error and context effects
Conversation volumeBrand mentions within the tracked queryNot the same as awareness or success
Share of voiceVolume share among the chosen brandsHighly sensitive to monitoring scope

7. Turn the finding into a decision

Five steps
  1. Fix the
    Question
  2. Validate the
    Query
  3. Raw and
    Rate Measures
  4. Contextualise
    Changes
  5. State It
    Carefully
  1. Fix the question and the period: the same platform coverage, the same date range.
  2. Validate the query: brand name, spelling variants, spam and duplicates.
  3. Give raw and normalised measures side by side: volume, rate and sample size together.
  4. Contextualise the changes: campaigns, product announcements, crises and platform algorithm shifts.
  5. State the conclusion carefully: separate observation from causal claim.
Example wording for a conclusion: “Over the tracked period, brand A had the higher conversation volume; brand B had the higher engagement per reach. Sentiment classes were labelled automatically and a sample was checked by hand. These indicators do not measure purchase preference on their own.” The strength of that sentence comes as much from what it does not claim.

A checklist

1

Is the question clear?

State at the top of the report which metric the comparison rests on.

2

Is coverage equal?

Date range and platform list must be identical for both brands.

3

Query validated?

Check brand-name clashes by hand against sample posts.

4

Spam rules

Bot, duplicate and reshare rules should be defined and written down in advance.

5

Denominator shown?

Every rate's denominator and sample size belong in the table.

6

Limits stated?

Model error, sampling bias and scope constraints should appear in the report.

One leaderboard is not enough

Comparing brands on social media is not a single ranking. Volume shows visibility, rates show engagement quality, and the sentiment split shows the approximate tone of the text. The three answer different questions and often put a different brand in front.

Presenting several measures within the same scope, with their denominators and their context, makes for a fairer and far more usable assessment. “Brand A is ahead” is not a finding until you have written down on which metric and within which scope.