[PYTHON] Ich habe versucht, den allgemeinen Zustand der VTuber-Kanalbetrachter zu visualisieren

Samari

Von den Kanten, die zwischen Distributoren verbunden sind, ist das Netzwerk, das nur die Kanten mit dem höchsten Gewicht von 10% anzeigt, wie folgt, und Betrachter werden häufig unter Distributoren gesehen, die zum selben Büro gehören, wie Nijisanji und Hollowive. Ich stellte fest, dass ich es trug. graph_author_union_(90, 0).png

Motiviert

Derzeit gibt es in der VTuber-Branche viele Niederlassungen wie Nijisanji, hololive, 774 inc., Nori Pro, upd8 usw., und jede Niederlassung hat viele Vertriebshändler. Natürlich gibt es auch einzelne Distributoren, die nicht zum Büro gehören. Distributoren veröffentlichen Videos für ungefähr eine Stunde in einem Tempo von ungefähr einmal täglich bis zu einigen Tagen. Wenn Sie die Videozeit für jedes Büro addieren, kann die Gesamtzeit der pro Tag geposteten Videos leicht 24 Stunden überschreiten. Daher ist es praktisch unmöglich, alle Videos von mehreren Büros aus anzusehen. Das Folgende ist meine registrierte Kanalspalte eines Tages, aber es ist schwer, alles zu sehen. .. .. ある日の登録チャンネル欄.png Vielleicht sind viele Menschen in der gleichen Situation. Daher wählt jede Person ein Video und einen Kanal nach ihrem Geschmack und Geschmack. Zu diesem Zeitpunkt dachte ich, dass es Spaß machen würde, zu visualisieren, welche Kanäle gleichzeitig leicht zu sehen sind, und versuchte, sie auszuführen.

Methode

Viele VTubers senden live, und Sie können während der Übertragung Kommentare veröffentlichen. Wenn Sie beispielsweise das Video (https://www.youtube.com/watch?v=Ypc_xKz--fY) von Hololives Luna Himemori (https://www.youtube.com/channel/UCa9Y57gfeY0Zro_noHRVrnw) abspielen, Sie können den folgenden Kommentarbereich zum Zeitpunkt der Live-Übertragung beiseite sehen. YouTube画面.png Dieses Kommentarprotokoll enthält Datum und Uhrzeit des Kommentars, den Namen des Betrachters, Spacha-Informationen und mehr. Dieses Mal werden wir Informationen zum Zuschauernamen verwenden, um die Beziehungen zwischen Kanälen zu bewerten. Sei $ U_i $ die Menge der Zuschauer, die einen Kanal $ i $ kommentiert haben, und definiere, wie viel die Zuschauer zwischen den Kanälen $ w_ {ij} $ gelitten haben, was das übliche Verhältnis der Kanäle $ i $ und $ j $ ist. .. $ w_{ij} := \frac{|U_i \cap U_j|}{|U_i \cup U_j|} $

Dies wird als Kantengewicht bei der Visualisierung als Netzwerk verwendet.

Berechnung und Visualisierung der Ähnlichkeit zwischen Kanälen

Der Datenerfassungszeitraum ist vom 1. Januar 2020 bis zum 30. Juni 2020. Außerdem haben wir nicht überprüft, ob die Kommentare aller Videos mit Kommentaren korrekt erhalten wurden. .. ..

Kommentardaten abrufen

Im folgenden Artikel wird eine Datenerfassungsmethode beschrieben. Verwenden Sie sie daher fast so, wie sie ist.

Als Beispiel speichere ich jedes Video im folgenden Format.

AuthorName BaseDate ChannelId Timestamp VideoId VideoLength
Moos max 2020-05-07 UC--A2dwZW7-M2kID0N6_lfA 2020-05-07 19:53:23 -Alnw7B1GBo 2953
Choco Corone 2020-05-07 UC--A2dwZW7-M2kID0N6_lfA 2020-05-07 19:54:58 -Alnw7B1GBo 2953
Schwarzer Hund 2020-05-07 UC--A2dwZW7-M2kID0N6_lfA 2020-05-07 19:55:08 -Alnw7B1GBo 2953
Oguna 2020-05-07 UC--A2dwZW7-M2kID0N6_lfA 2020-05-07 19:55:56 -Alnw7B1GBo 2953
Hochspannung Freitag 2020-05-07 UC--A2dwZW7-M2kID0N6_lfA 2020-05-07 19:56:05 -Alnw7B1GBo 2953

Nur VideoLength ist Text. .. .. Ich werde es dieses Mal nicht benutzen. .. ..

Erstellen eines Datensatzes

Erstellen Sie zunächst eine Liste der Zuschauer, die den Datenzeitraum für jeden Kanal kommentiert haben. Dies kann durch Zusammenführen aller oben erhaltenen Kommentarlisten erfolgen. Der folgende Code versucht, die Anzahl der Kommentare zu zählen. Dies dient jedoch der Bequemlichkeit einer anderen Aufgabe und ist nicht wesentlich mit dieser Aufgabe verbunden.

df = pd.concat([pd.read_pickle(path) for path in comment_paths])
counts = df.groupby(['AuthorName', 'ChannelId', 'VideoId', 'BaseDate']).size().to_frame('Count').reset_index()

Das Format ist wie folgt.

AuthorName ChannelId VideoId BaseDate Count
chro nicle UCwrjITPwG4q71HzihV2C7Nw H7wgvBbxo1U 2020-06-30T00:00:00 1
Fazias UChAnqc_AY5_I3Px5dig3X1Q Q7DS6uaInMA 2020-06-30T00:00:00 26
Yumekui Shuga UCuvk5PilcvDECU7dDZhQiEw 6uiQOEDmD6U 2020-06-30T00:00:00 91
Fatin Thifal UCOmjciHZ8Au3iKMElKXCF_g ZrFJpafDKVw 2020-06-30T00:00:00 3
Katatsumuri Zustand der Bettdecke UC6oDys1BGgBsIC3WhG1BovQ QHTLzahEiX4 2020-06-30T00:00:00 1

Benachbarte Matrix

Wie bereits erwähnt, berechnen wir diesmal die Abdeckung des Zuschauers zwischen den Kanälen. Dies kann leicht erreicht werden, indem eine Benutzerliste für jeden Kanal erstellt und eine festgelegte Operation ausgeführt wird.

def corr_by_author_set_union(counts, channels):
    corr = pd.DataFrame().assign(Channel=channels).set_index('Channel')
    tmp = counts.loc[:, ['ChannelId', 'AuthorName']].drop_duplicates()
    channelId_to_set = {ch: set(tmp[tmp.ChannelId == ch].AuthorName) for ch in channels}
    for  ch1 in channels: 
        corr[ch1] = [(len(channelId_to_set[ch1] & channelId_to_set[ch2]) / \
                    len(channelId_to_set[ch1] | channelId_to_set[ch2])) for ch2 in channels]
    return corr

Darstellung des Graphen

Zeichnen wir nun die Grafik. Der Code ist fast der gleiche wie auf der folgenden Site.

def create_graph(df, threshold=0.5, is_directed=True):
    assert set(df.index) == set(df.columns)

    #Erstellen Sie ein Diagramm
    if is_directed:
        graph = nx.DiGraph()
    else:
        graph = nx.Graph()

    #Knoten hinzufügen
    for col in df.columns:
        if not graph.has_node(col):
            graph.add_node(col)

    #Kante hinzufügen
    for a, b in itertools.combinations(df.columns, 2):
        if a == b or graph.has_edge(a, b):
            continue
        val = df.loc[a, b]
        if abs(val) < threshold:
            continue
        graph.add_edge(a, b, weight=val)

    return graph

def draw_char_graph(G, fname, edge_cmap=plt.cm.Greys, figsize=(16, 8)):
    plt.figure(figsize=figsize)
    weights = [G[u][v]['weight'] for u, v, in G.edges()]
    pos = nx.spring_layout(G, k=16)

    nodes = pos.keys()
    colors = list(set([channel_to_color[n] for n in nodes]))
    color_to_id = {colors[i]: i for i in range(len(colors))}
    angs = np.linspace(0, 2*np.pi, 1+len(colors))
    repos = []
    rad = 3.5
    for ea in angs:
        repos.append(np.array([rad*np.cos(ea), rad*np.sin(ea)]))
    for ea in pos.keys():
        posx = 0
        posx = color_to_id[channel_to_color[ea]]
        pos[ea] += repos[posx]

    nx.draw(G,
            pos, 
            node_color=[channel_to_color[n] for n in G.nodes()],
            edge_cmap=edge_cmap,
            edge_vmin=-3e4,
            width=weights,
            with_labels=True,
            font_family='Yu Gothic',
            font_size=8,
            font_color='green')
    plt.savefig(fname, dpi=128)
    plt.show()

Erstellen und zeichnen Sie mit diesen ein Diagramm.

Ganzes Netzwerk

Die Linienstärke entspricht dem hohen Prozentsatz der gemeinsamen Betrachter. .. ..

union_corr = corr_by_author_set_union(channels)
#Es ist schwer zu verstehen, ob es sich um ChannelId handelt. Schreiben Sie es daher in ChannnelName um
union_corr = rename_ChannelId_to_ChannelName(union_corr)
graph = create_graph(union_corr, threshold=0, is_directed=False)
draw_char_graph(graph, 'fig/graph_author_union.png', figsize=(16, 16))

―― Insgesamt ist die Richtung von Nijisanji gerichtet, und der Prozentsatz der Personen, die gleichzeitig Nijisanji und andere Büros betrachten, ist hoch.

graph_author_union.png

Ganzes Netzwerk (nur die oberen 10% der Kantengewichte)

Da die Anzahl der Anzeigen im vorherigen Diagramm zu groß ist, sollten Sie die Anzahl der Kanten reduzieren. 10% ist ein Gefühl. Da hier nur die obersten 10% dargestellt werden, kann hier eine Linie gezogen werden, die interpretiert werden kann, dass die Abdeckung des Betrachters zwischen den Kanälen sehr hoch ist. .. ..

# (Rand th, betweenness_centrality)
pairs = [(90, 0)]
df = union_corr.copy()
for pair in pairs:
    th = np.percentile(df.fillna(0).values.ravel(), pair[0])
    print(pair, th)
    graph = create_graph(df, threshold=th, is_directed=False)
    draw_char_graph(graph , 'fig/graph_author_union_{}.png'.format(pair), figsize=(16, 16))

――Hohe gemeinsame Zuschauerzahl im selben Büro

graph_author_union_(90, 0).png

Büronetzwerk

Hier sind nur die oberen 10% der Kanten eingezeichnet.   Als persönlicher Eindruck kann Folgendes berücksichtigt werden, wenn die Verbindung zum Büro schwach ist.

――Das gesamte Büro ist verbunden und das Publikum ist schwach abgedeckt. ――Die Verbindung mit der Außenseite des Büros ist stark, und wenn die Innenseite des Büros angezeigt wird, erscheint die Verbindung schwach.

Internes Netzwerk von Nijisanji

――Ich verstehe nicht, weil sich die Linien zu stark überlappen. graph_author_union_btw_Nijisanji Japan_and_Nijisanji Japan.png

Untere und obere 3 Kanäle mit Gewichten, die mit jedem Knoten verbunden sind

index Mean kind
Azuchi Pfirsich 0.02581 Nijisanji Japan
♥ ️ ♠ ️ Aussage Arisu ♦ ️ ♣ ️ 0.03546 Nijisanji Japan
Gilzaren III Season 2 0.04463 Nijisanji Japan
Akina Saegusa/ Saegusa Akina 0.13969 Nijisanji Japan
Amamiya Kokoro/Kokoro Amamiya [Nijisanji-Zugehörigkeit] 0.14043 Nijisanji Japan
Gwell Os Mädchen/Gwelu Os Gar [Nijisanji] 0.14336 Nijisanji Japan

Netzwerk in hololive

――Wie persönlich gefühlt ――Es fällt auf, dass durch die Abdeckung des Publikums ein Dreieck gebildet wird. .. .. ich fühle

graph_author_union_btw_Hololive Japan_and_Hololive Japan.png

index Mean kind
Mel Channel Nachthimmel Mel Channel 0.1314 Hololive Japan
SoraCh.Tokinosora-Kanal 0.1653 Hololive Japan
Nakiri Ayame Ch.Hyakuki Ayame 0.1859 Hololive Japan
Kanata Ch.Kanata Amane 0.2664 Hololive Japan
Watame Ch.Zum quadratischen Wickeln 0.2684 Hololive Japan
Shion Ch.Shisaki Zion 0.2699 Hololive Japan

Netzwerk innerhalb von Holostars

――Wie persönlich gefühlt

graph_author_union_btw_Holostars_and_Holostars.png

index Mean kind
Izuru Ch.Spieler Izuru 0.1544 Holostars
Kira Ch.Spiegelblick Kira 0.1688 Holostars
Rikka ch.Ritsumei 0.1748 Holostars
astel ch.Astel 0.2173 Holostars
Shien Ch.Kageyama Cien 0.2178 Holostars
Temma Ch.Kishido Tenshin 0.2222 Holostars

774 Netzwerk in .inc

――Ist das Publikum von Sugariri, Hanist und Animare geteilt?

graph_author_union_btw_774 inc._and_774 inc..png

index Mean kind
Patra Channel /Suo Patra [Hanist] 0.1307 774 inc.
Haneru Channel /Inaba Haneru [Ani Mare] 0.1335 774 inc.
CAMOMI Camomi Channel [Kamomi Camomi] 0.1369 774 inc.
Izumi Channel /Izumi Yuzuhara [Animare] 0.1931 774 inc.
Anna Channel /Anna Torajo [Sugariri] 0.1949 774 inc.
Rene Channel /Rin Ryugasaki [Sugariri] 0.2055 774 inc.

Netzwerk in upd8

――Die Linie ist dünn und das Publikum wird nicht viel abgedeckt ――Die Linie zwischen Onkel Bami Fleisch ist dick

graph_author_union_btw_upd8_and_upd8.png

index Mean kind
Motor Kazumi 0.03281 upd8
Yuuki Channel [Verdammte Sexualerziehung] 0.03323 upd8
Cheri High Homecoming Abteilung 0.03345 upd8
Nora Cat Channel 0.04661 upd8
Tomari Mari channel /Kaninchen Mari-Chan 0.04728 upd8
Magurona-Kanal 0.04752 upd8

Netzwerk innerhalb von Nori Pro

――Seit die Linie verschwindet, zeichnen Sie nur hier die oberen 25% der Linie

graph_author_union_btw_Noripuro_and_Noripuro.png

index Mean kind
Tsukuda Norio Channel [Tamaki Inuyama] 0.2353 Noripuro
Aimiya Milch Milch Enomiya 0.2453 Noripuro
Shirayuki Mishiro 0.2591 Noripuro
Tsukuda Norio Channel [Tamaki Inuyama] 0.2353 Noripuro
Aimiya Milch Milch Enomiya 0.2453 Noripuro
Shirayuki Mishiro 0.2591 Noripuro

Persönliches Netzwerk

»Ich habe es nach dem Planen bemerkt, aber Yui Yui und Shia Minase gehören zum Büro. Es ist auch offensichtlich, dass sich die Zielgruppen überschneiden

graph_author_union_btw_Other VTubers_and_Other VTubers.png

index Mean kind
Kobana 0.08867 Other VTubers
Kazemiya Festival/ Matsuri Channel 0.09249 Other VTubers
Tenso Hiyo 0.09265 Other VTubers
Makio [Einzelperson] 0.10765 Other VTubers
Minase Shia [Shia Channel] 0.11933 Other VTubers
Yui Yui 〖YouTube〗 0.12053 Other VTubers

Netzwerk mit einem anderen Büro

――Wenn Sie alle Kombinationen ausführen, werden viele Bilder angezeigt, also nur zwischen Nijisanji und hololive ――Ist es der Einfluss der Ozora-Familie, dass Subaru Ozora und Keisuke Maimoto im Gewicht der verbundenen Kante höher eingestuft werden?

graph_author_union_btw_Hololive Japan_and_Nijisanji Japan.png

Von den hololiven Kanälen sind die unteren 3 des Gewichtsmittelwerts der mit dem Regenbogen verbundenen Kanten

index Mean kind
Mel Channel Nachthimmel Mel Channel 0.02613 Hololive Japan
SoraCh.Tokinosora-Kanal 0.03727 Hololive Japan
Towa Ch.Ewige Towa 0.03840 Hololive Japan
Kanata Ch.Kanata Amane 0.05254 Hololive Japan
Marine Ch.Schatzglocke Marine 0.05539 Hololive Japan
Subaru Ch.Himmel Subaru 0.05971 Hololive Japan

Unter den Kanälen von Nijisanji sind die unteren 3 des Gewichtsmittelwerts der Kante mit hololive verbunden

index Mean kind
Azuchi Pfirsich 0.003585 Nijisanji Japan
Harusaki Air 0.009090 Nijisanji Japan
Gilzaren III Season 2 0.009123 Nijisanji Japan
[3. Klasse 0 Gruppe] Mirei Gunmichis Klassenzimmer 0.085043 Nijisanji Japan
Keisuke Maimoto 0.087824 Nijisanji Japan
Ruru Suzuhara [Nijisanji-Zugehörigkeit] 0.096265 Nijisanji Japan

Impressionen

――Wenn Sie die Zusammenarbeit verbessern, wird das Publikum überfordert sein, das ist richtig ――Es scheint interessant zu sein, Kernextraktion und Clusteranalyse durchzuführen.

Recommended Posts

Ich habe versucht, den allgemeinen Zustand der VTuber-Kanalbetrachter zu visualisieren
[Python] Ich habe versucht, die folgende Beziehung von Twitter zu visualisieren
Ich habe versucht, die Trapezform des Bildes zu korrigieren
Ich habe versucht, die Texte von Hinatazaka 46 zu vektorisieren!
Ich habe die übliche Geschichte ausprobiert, Deep Learning zu verwenden, um den Nikkei-Durchschnitt vorherzusagen
Ich habe versucht, die Grundform von GPLVM zusammenzufassen
Ich habe versucht, die Tweets von JAWS DAYS 2017 mit Python + ELK einfach zu visualisieren
Ich habe versucht, den negativen Teil von Meros zu löschen
Ich habe versucht, die Stimmen der Sprecher zu klassifizieren
Ich habe versucht, den Grad der Koronavirusinfektion auf der Seekarten-Wärmekarte anzuzeigen
Ich habe versucht, die String-Operationen von Python zusammenzufassen
Python-Übung 100 Schläge Ich habe versucht, den Entscheidungsbaum von Kapitel 5 mit graphviz zu visualisieren
Ich habe versucht, die Eigenschaften der neuen Informationen über mit dem Corona-Virus infizierte Personen mit Wordcloud zu visualisieren
[Erste Datenwissenschaft ⑥] Ich habe versucht, den Marktpreis von Restaurants in Tokio zu visualisieren
Ich habe versucht, die Laufdaten des Rennspiels (Assetto Corsa) mit Plotly zu visualisieren
Ich habe versucht, die Entropie des Bildes mit Python zu finden
[Pferderennen] Ich habe versucht, die Stärke des Rennpferdes zu quantifizieren
Ich habe versucht, die Standortinformationen des Odakyu-Busses zu erhalten
[TF] Ich habe versucht, das Lernergebnis mit Tensorboard zu visualisieren
[Maschinelles Lernen] Ich habe versucht, die Theorie von Adaboost zusammenzufassen
Ich habe versucht, das lokale Minimum der Goldstein-Preis-Funktion zu bekämpfen
Ich habe versucht, den Ball zu bewegen
Ich habe versucht, den Abschnitt zu schätzen.
Ich habe versucht, den Stromverbrauch meines Hauses mit Nature Remo E lite zu visualisieren
[Verarbeitung natürlicher Sprache] Ich habe versucht, die Bemerkungen jedes Mitglieds in der Slack-Community zu visualisieren
[Linux] Ich habe versucht, die Ressourcenbestätigungsbefehle zusammenzufassen
Ich habe versucht, den Index der Liste mithilfe der Aufzählungsfunktion abzurufen
Ich habe versucht, die Bewässerung des Pflanzgefäßes mit Raspberry Pi zu automatisieren
Ich habe versucht, das SD-Boot-Image von LicheePi Nano zu erstellen
Ich habe versucht, den Getränkepräferenzdatensatz durch Tensorzerlegung zu visualisieren.
Ich habe versucht, Boeing die Geigenleistung durch Posenschätzung vorzustellen
Ich habe versucht, die häufig verwendete Implementierungsmethode von pytest-mock zusammenzufassen
Ich habe versucht, die Effizienz der täglichen Arbeit mit Python zu verbessern
Ich habe den asynchronen Server von Django 3.0 ausprobiert
Ich habe versucht, den Befehl umask zusammenzufassen
Ich versuchte das Weckwort zu erkennen
Ich habe versucht, die grafische Modellierung zusammenzufassen.
Ich habe versucht, das Umfangsverhältnis π probabilistisch abzuschätzen
Ich habe versucht, die COTOHA-API zu berühren
[Python] Ich habe versucht, das Preisgeld von "ONE PIECE" über 100 Millionen Zeichen mit matplotlib zu visualisieren.
Ich habe versucht, das Gesichtsbild mit sparse_image_warp von TensorFlow Addons zu transformieren
[Python] Ich habe versucht, die Nacht der Galaxienbahn mit WordCloud zu visualisieren!
Ich habe versucht, die Trefferergebnisse von Hachinai mithilfe der Bildverarbeitung zu erhalten
Ich habe versucht, die Beispielnachrichten zur Geschäftsintegration in Amazon Transcribe zu übertragen
Ich habe versucht, die Ähnlichkeit der Frageabsicht mit Doc2Vec von gensim abzuschätzen
Ich habe versucht, die Genauigkeit meines eigenen neuronalen Netzwerks zu verbessern
Ich habe versucht, die Version 2020 mit 100 Sprachverarbeitung zu lösen [Kapitel 3: Reguläre Ausdrücke 25-29]
Ich habe versucht, die Bewegungen von Wiire-Playern automatisch mit Software zu extrahieren
Ich habe versucht, die logische Denkweise über Objektorientierung zusammenzufassen.
Ich habe versucht, die optimale Route des Traumlandes durch (Quanten-) Tempern zu finden
Ich habe versucht, die Phase der Geschichte mit COTOHA zu extrahieren und zu veranschaulichen
Ich habe versucht, die Negativität von Nono Morikubo zu analysieren. [Vergleiche mit Posipa]
Ich habe versucht, die Standardrolle neuer Mitarbeiter mit Python zu optimieren
Ich habe versucht, das RSS des Top-Songs des iTunes Store automatisch abzurufen
Ich habe versucht, die Filminformationen der TMDb-API mit Python abzurufen
Ich habe versucht, alle Entscheidungsbäume des zufälligen Waldes mit SVG zu visualisieren
Ich habe versucht, den Höhenwert von DTM in einem Diagramm anzuzeigen
Mit COTOHA habe ich versucht, den emotionalen Verlauf des Laufens von Meros zu verfolgen.