[PYTHON] Analyse der Lebensdauer der Technologie mit Qiita-Artikeldaten ~ Überlebenszeitanalyse mithilfe des Inhaltsprotokolls ~

Dieser Artikel ist der 19. Tag des Adventskalenders der NTT Docomo SI-Abteilung.

Hallo! Es ist Hashimoto vom Read-Ahead-Engine-Team. Im Geschäft arbeiten wir daran, Technologien zur Analyse personenbezogener Daten für den Agentenservice zu entwickeln.

In diesem Artikel werden wir ** eine Methode zur quantitativen Bewertung der Lebensdauer von Inhalten (kontinuierliche Artikelveröffentlichung) vorstellen, indem wir eine Überlebenszeitanalyse auf von Qiita veröffentlichte Artikeldaten anwenden **.

Die Überlebenszeitanalyse ist eine Methode zur Analyse der Beziehung zwischen dem Zeitraum bis zum Eintreten des Ereignisses und dem Ereignis. Im Allgemeinen wird es verwendet, um den Zeitraum bis zum Todesereignis eines Patienten (menschliches Leben) im medizinischen Bereich und den Zeitraum bis zu einem Komponentenausfallereignis (Teillebensdauer) im technischen Bereich zu analysieren. Dieses Mal werde ich in ** Qiita-Post-Daten die Lebensdauer technischer Posts ** analysieren, indem ich davon ausgehe, dass der Benutzer die Veröffentlichung von Artikeln einer bestimmten Technologie kontinuierlich eingestellt hat!: Muskel:

Mithilfe der Überlebenszeitanalyse kann bewertet werden, ob der Inhalt eine lange / kurze Lebensdauer hat oder ob die Nutzungsrate des Inhalts langsam / plötzlich abnimmt. Es gibt verschiedene Verwendungsmöglichkeiten für die Bewertungsergebnisse, z. B. das Erstellen der Funktionsmenge der Inhaltsklassifizierungsaufgabe, das Erstellen der Funktionsmenge der Benutzerklassifizierungsaufgabe unter Verwendung des Inhaltsverwendungsverlaufs oder das Treffen einer Entscheidung für die Inhaltsempfehlungsmaßnahme.

Weitere Informationen zur Analyse der Überlebenszeit finden Sie in den folgenden Artikeln und Büchern.

Analysefluss

Der grobe Ablauf der Analyse in diesem Artikel ist wie folgt.

  1. ** Datenvorverarbeitung **: Berechnet den Zeitraum, in dem Qiita-Artikel mit einem bestimmten Tag an alle Benutzer gesendet wurden, und das Flag, ob die Veröffentlichung gestoppt wurde oder nicht.
  2. ** Anwendung auf das Wyble-Modell **: Unter Verwendung der obigen Angaben als Eingabedaten wird das Wyble-Modell angepasst (die Parameter des Wyble-Modells werden geschätzt) und die aus dem Wyble-Modell erhaltene Überlebensratenkurve ausgegeben.
  3. ** Vergleich der Überlebensrate für jedes Tag **: Führen Sie die obigen Schritte für mehrere Tags (Techniken) durch und vergleichen Sie die Parameter der Überlebensratenkurve.

Die Ausführungsumgebung des Programms im Artikel ist Python3.6, macOS 10.14.6. Wir werden auch eine Bibliothek zur Analyse der Überlebenszeit mit dem Namen Lebenslinien 0.22.9 verwenden.

Über den Datensatz

Dieser Artikel verwendet den unten erhaltenen Qiita-Datensatz. Erstellt einen Datensatz aus Qiitas Beitrag

Dieser Datensatz ist ein Datensatz des Artikelposting-Verlaufs des Benutzers, der von der von Qiita bereitgestellten API erfasst wurde. Sie können den Buchungsverlauf von 2011 bis 2018 überprüfen. Bei der Durchführung dieser Analyse

Diese Daten wurden übernommen, weil sie die beiden oben genannten Bedingungen erfüllen.

Wenn Sie die Daten mit pandas dataframe lesen, ist dies wie folgt.

import pandas as pd

df = pd.read_csv('qiita_data1113.tsv', sep='\t')
df.head()
created_at updated_at id title user likes_count comments_count page_views_count url tags
2011-09-30T22:15:42+09:00 2015-03-14T06:17:52+09:00 95c350bb66e94ecbe55f Gentoo ist süß Gentoo {'description': ';-)',... 1 0 NaN https://... [{'name': 'Gentoo', 'versions': []}]
2011-09-30T21:54:56+09:00 2012-03-16T11:30:14+09:00 758ec4656f23a1a12e48 Erdbeben-Bulletin-Code {'description': 'Emi Tamak... 2 0 NaN https://... [{'name': 'ShellScript', 'versions': []}]
2011-09-30T20:44:49+09:00 2015-03-14T06:17:52+09:00 252447ac2ef7a746d652 parsingdirtyhtmlcodesiskillingmesoftly {'description': 'Rufen Sie nicht Github an... 1 0 NaN https://... [{'name': 'HTML', 'versions': []}]
2011-09-30T14:46:12+09:00 2012-03-16T11:30:14+09:00 d6be6e81aba24f39e3b3 Objective-Wie wird die folgende Variable x bei der Implementierung der C-Klasse behandelt?... {'description': 'Hallo. Hatena... 2 1 NaN https://... [{'name': 'Objective-C', 'versions': []}]
2011-09-28T16:18:38+09:00 2012-03-16T11:30:14+09:00 c96f56f31667fd464d40 HTTP::Request->AnyEvent::HTTP->HTTP::Response {'description'... 1 0 NaN https://... [{'name': 'Perl', 'versions': []}]

Übrigens werden in jedem Artikel bis zu 3 Tags aus der Tags-Spalte extrahiert, und die Rangfolge basierend auf der Gesamtzahl lautet wie folgt.

index tag
0 JavaScript 14403
1 Ruby 14035
2 Python 13089
3 PHP 10246
4 Rails 9274
5 Android 8147
6 iOS 7663
7 Java 7189
8 Swift 6965
9 AWS 6232

Analytische Verarbeitung

1. Vorbehandlung

Extrahieren Sie die erforderlichen Daten aus dem DataFrame, der den obigen Datensatz gelesen hat.

df_base = <get tags>
df_base.head()
user_id time_stamp tag
kiyoya@github 2011-09-30 22:15:42+09:00 Gentoo
hoimei 2011-09-30 21:54:56+09:00 ShellScript
inutano 2011-09-30 20:44:49+09:00 HTML
hakobe 2011-09-30 14:46:12+09:00 Objective-C
motemen 2011-09-28 16:18:38+09:00 Perl
ichimal 2011-09-28 14:41:56+09:00 common-lisp
l_libra 2011-09-28 08:51:27+09:00 common-lisp
ukyo 2011-09-27 23:57:21+09:00 HTML
g000001 2011-09-27 22:29:04+09:00 common-lisp
suginoy 2011-09-27 10:20:28+09:00 Ruby

Created \ _at und Tag wurden als user_id, time \ _stamp aus jedem Datensatz extrahiert. Für diejenigen mit mehreren Tags haben wir bis zu 5 herausgenommen und jeweils als einen Datensatz zusammengefasst. Beachten Sie, dass Schwankungen der Tag-Notation (Golang und Go, Rails und RubyOnRails usw.) nicht berücksichtigt werden.

Konvertiert das Datenformat in zweispaltige Daten-, Lebensdauer- und Ereignisflags zur Eingabe in das Lebenslinienmodell. Da diese Daten kein eindeutiges Ereignis (Artikel nicht mehr veröffentlichen) oder keine Überlebenszeit (Dauer der kontinuierlichen Artikelveröffentlichung) anzeigen, müssen sie unabhängig definiert werden.

In diesem Abschnitt wird ein Ereignis als Ereignisereignis definiert, wenn die folgenden beiden Bedingungen erfüllt sind.

  1. Ein Ereignis tritt ein, wenn der Zeitraum zwischen zwei benachbarten Pfosten θ Tage oder mehr beträgt
  2. Ein Ereignis tritt ein, wenn die Frist für den Beobachtungszeitraum und der Zeitraum der letzten Veröffentlichung θ Tage oder mehr betragen.

Wenn die Frist für den Beobachtungszeitraum und der Zeitraum für die letzte Veröffentlichung weniger als θ Tage beträgt, wird dies als Beendigung der Beobachtung behandelt.

Es ist ein wenig schwer zu verstehen, deshalb werde ich es mit einer Figur erklären. event_definition.png

Die obige Abbildung zeigt den Zeitpunkt der Artikelveröffentlichung in chronologischer Reihenfolge für 3 Benutzer. Benutzer A hat eine Frist für den Beobachtungszeitraum und den letzten Buchungszeitraum von θ Tagen oder mehr. Daher wird das Ereignis nach dem letzten Beitrag stattfinden. Benutzer B hat für die letzten beiden Beiträge einen Zeitraum von θ Tagen oder mehr. Auch in diesem Fall wird es als Ereignisereignis beurteilt. Für Benutzer C beträgt der Zeitraum zwischen zwei benachbarten Posts weniger als θ, und die Frist für den Beobachtungszeitraum und den Zeitraum des letzten Posts beträgt weniger als θ Tage. Daher wird es als Beobachtungsabbruch behandelt. In Bezug auf die Überlebenszeit wird der Zeitraum bis zum Eintreten des Ereignisses oder der Zeitraum bis zum Stichtag des Beobachtungszeitraums als Überlebenszeit definiert.

Dieses Mal haben wir uns entschlossen, anhand der oben genannten Regeln zu bestimmen, ob ein Ereignis aufgetreten ist oder nicht, und die Überlebenszeit. Wenn die obige Logik als `make_survival_dataset ()` definiert und implementiert ist, ist dies wie folgt. Diesmal ist θ = 365 Tage. Darüber hinaus wird der Beobachtungszeitraum 2018/12/01 angegeben. Es wird angenommen, dass ein nach einem bestimmten Tag gefilterter DataFrame als Argument eingegeben wird.

import datetime
import pytz

def make_survival_dataset(df_qiita_hist, n = 365):
    id_list = []
    duration_list = []
    event_flag_list = []
    
    for index, (userid, df_user) in enumerate(df_qiita_hist.groupby('user_id')):
        #Fügen Sie am Ende eine Beobachtungsfrist hinzu
        dt = datetime.datetime(2018, 12, 1, tzinfo=pytz.timezone("Asia/Tokyo"))
        last = pd.Series(['test', dt, 'last'], index=['user_id', 'time_stamp', 'tag'], name='last')
        df_user= df_user.append(last)
        
        #Berechnen Sie den Zeitraum zwischen zwei benachbarten Pfosten(Der Anfang der Liste ist Keine.)
        day_diff_list = df_user.time_stamp.diff().apply(lambda x: x.days).values
        
        #Listen mit einer Länge von 2 oder weniger werden von der Berechnung ausgeschlossen.
        if len(day_diff_list) <= 2:
            continue
            
        #Suchen Sie, ob ein Ereignis auftritt oder nicht.
        event_flag = False
        #Liste zur Berechnung des Zeitraums bis zum Eintreten des Ereignisses
        day_list = []
        
        for day in day_diff_list[1:]:
            if day >= n:
                event_flag = True
                break
        
            day_list.append(day)
            
        #Berechnen Sie den Zeitraum bis zum Eintreten des Ereignisses
        s = sum(day_list)
        
        #Personen mit einem Zeitraum von 0 sind ausgeschlossen
        if s == 0:
            continue
        
        #Erstellen Sie einen DataFrame
        id_list.append(userid)
        duration_list.append(s)
        event_flag_list.append(event_flag)
        
        
    return pd.DataFrame({'userid':id_list, 'duration':duration_list, 'event_flag': event_flag_list})

Extrahieren Sie den Datensatz mit dem Python-Tag und geben Sie ihn in make \ _survival \ _dataset ein.

df_python = df_base[df_base['tag'] == 'Python'].sort_values('time_stamp')
df_surv = make_survival_dataset(df_python, n=365)
df_surv.head()
userid duration event_flag
33yuki 154.0 False
5zm 432.0 False
AketiJyuuzou 57.0 True
AkihikoIkeda 308.0 False
Amebayashi 97.0 True

Jetzt haben Sie die Daten, die Sie in das Wible-Modell eingeben können.

2. Anwendung auf das Wible-Modell

Geben Sie die oben erstellten Daten in das Wible-Modell ein und führen Sie die Parameteranpassung und das Zeichnen der Überlebenskurven durch. Lassen Sie uns hier zusätzlich zu Python Daten mit Ruby-Tags zeichnen.

import lifelines
%matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'IPAexGothic'

_, ax = plt.subplots(figsize=(12, 8))

# Python
name = 'Python'
df_surv = make_survival_dataset(df_base[df_base['tag'] == name].sort_values('time_stamp'), n=365)
wf = lifelines.WeibullFitter().fit(df_surv['duration'], df_surv['event_flag'], label=name)
wf.plot_survival_function(ax=ax, grid=True)

# Ruby
name = 'Ruby'
df_surv = make_survival_dataset(df_base[df_base['tag'] == name].sort_values('time_stamp'), n=365)
wf = lifelines.WeibullFitter().fit(df_surv['duration'], df_surv['event_flag'], label=name)
wf.plot_survival_function(ax=ax, grid=True)

ax.set_ylim([0, 1])
ax.set_xlabel('Lebenszeit(Tag)')
ax.set_ylabel('Überlebensrate')

python_ruby_surv.png

Die vertikale Achse ist die Anzahl der Tage und die vertikale Achse ist die Überlebensrate (Prozentsatz der Benutzer, die weiterhin Beiträge verfassen). Insgesamt können wir sehen, dass die Überlebensrate mit fortschreitender Anzahl von Tagen abnimmt. Wenn wir uns auf Python konzentrieren, können wir sehen, dass die Überlebensrate zum Zeitpunkt von 1500 Tagen knapp unter 0,2 liegt. Dies bedeutet, dass 20% der Personen 1500 Tage nach Beginn der Veröffentlichung weiterhin Beiträge veröffentlichen. Auf der anderen Seite bedeuten die verbleibenden 80%, dass die Buchung kontinuierlich eingestellt wird. Nach 1500 Tagen Vergleich von Python und Ruby können Sie feststellen, dass es einen Unterschied von etwa 10% gibt. Soweit wir sehen können, ** haben Python-Artikel insgesamt eine längere Überlebenszeit als Ruby-Artikel, und es besteht die Tendenz zur kontinuierlichen Veröffentlichung von Artikeln. ** Die Langlebigkeit von Python scheint durch die jüngste Zunahme der Nachfrage als Werkzeug für maschinelles Lernen / Datenanalyse beeinflusst zu werden.

Auf diese Weise ist es durch Definieren des Ereignisses und der Überlebenszeit für das Inhaltsprotokoll und Durchführen einer Überlebenszeitanalyse möglich, die Überlebenszeit des Inhalts zu vergleichen.

3. Vergleich der Parameter der Überlebensratenkurve für jedes Tag

Gemäß der Lebenslinien-Dokumentation basiert die Überlebensratenkurve auf der folgenden Formel. Es wird basierend auf gezeichnet.

S(t) = \exp(-(t/\lambda)^{\rho}) \ where\ \lambda > 0, \rho > 0

Die Überlebensratenkurve hängt von den Parametern λ und ρ ab, und die Anpassungsfunktion von Weibull Fitter besteht in der Berechnung der obigen Parameter. Daher kann durch Auftragen der von WeibullFitter erhaltenen Werte von λ und ρ in einem zweidimensionalen Diagramm die Ähnlichkeit der Überlebensratenkurve für jedes Tag visuell bestätigt werden.

Ich habe die Tags mit 1000 oder mehr Posting-Benutzern im Datensatz eingegrenzt und sie geplottet.

param_plot_1000.png

Λ ist auf der vertikalen Achse und ρ auf der horizontalen Achse aufgetragen.

Im Allgemeinen ist die Steigung der Überlebensratenkurve im Laufe der Zeit tendenziell steiler, je größer der Wert von λ ist, je länger die Überlebenszeit ist und je größer der Wert von ρ ist. Wenn Sie grob nach der Größe von λ und ρ klassifizieren, sieht es folgendermaßen aus: Denken:

Es ist in der folgenden Abbildung zusammengefasst. param_plot_comment.png

Für die meisten Dinge habe ich den Eindruck, dass es der Interpretation entspricht (?). Es ist interessant, dass der Unterschied in den Parametern mit der Art der tatsächlichen Technologie zusammenhängt. Es gibt einige Feinheiten wie C # und Objective-C, aber ...: Denken:

Zusammenfassung

Wir führten eine Überlebenszeitanalyse der Qiita-Artikeldaten durch und klassifizierten den Inhalt unter den beiden Gesichtspunkten der Länge der Überlebenszeit und des Grads der Änderung der Steigung der Überlebensratenkurve. Es war eine grobe Interpretation, aber ich fand, dass es mit dem Unterschied in den Parametern und der Art der Technologie zusammenhängt. Ich denke, der in diesem Artikel vorgestellte Inhalt ist eine Methode, die auf andere Inhaltsprotokolle angewendet werden kann. Wenn Sie die Möglichkeit haben, das Inhaltsnutzungsprotokoll zu berühren, lesen Sie es bitte. Abschließend werde ich einige der zusätzlichen Analyseergebnisse teilen und abschließen. Na dann, ein gutes Jahr ~: raised_hand:

Bonus

iOS V.S. Android ios_android_surv.png

Emacs V.S. Vim emacs_vim_surv.png

Typisches Deep Learning Framework

deep_learning.png

Parameterdiagramm mit mehr als 500 Posting-Benutzern

param_plot_500.png

Recommended Posts

Analyse der Lebensdauer der Technologie mit Qiita-Artikeldaten ~ Überlebenszeitanalyse mithilfe des Inhaltsprotokolls ~
Verkürzung der Analysezeit von Openpose mithilfe von Sound
Empfehlung zur Datenanalyse mit MessagePack
Zeitreihenanalyse 3 Vorverarbeitung von Zeitreihendaten
Veranschaulichen Sie sofort die vorherrschende Periode in Zeitreihendaten mithilfe der Spektralanalyse
Eine Einführung in die Datenanalyse mit Python - Um die Anzahl der Videoansichten zu erhöhen -
So erhalten Sie Artikeldaten mithilfe der Qiita-API
Zeigen Sie Details zu Zeitreihendaten mit Remotte an
Überprüfen Sie den Status der Daten mit pandas_profiling
Scraping der Gewinndaten von Zahlen mit Docker
Vorhersage der Zielzeit eines vollständigen Marathons mit maschinellem Lernen - Visual: Visualisierung von Daten mit Python-
[In-Database Python Analysis Tutorial mit SQL Server 2017] Schritt 4: Feature-Extraktion von Daten mit T-SQL
Ich wollte nur die Daten des gewünschten Datums und der gewünschten Uhrzeit mit Django extrahieren