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.
Der grobe Ablauf der Analyse in diesem Artikel ist wie folgt.
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.
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 |
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.
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.
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.
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')
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.
Gemäß der Lebenslinien-Dokumentation basiert die Überlebensratenkurve auf der folgenden Formel. Es wird basierend auf gezeichnet.
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.
Λ 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:
** Großes λ: Langes Überleben **
PHP (und Laravel), Ruby (und Rails), C #, iOS, Android usw.
Eindruck, dass es häufig in Produkten verwendet wird (viele Benutzer?) Und dass es viele Programmiersprachen (und Frameworks) und mobile Entwicklung gibt. ――Da es die Sprache und das Framework ist, die für das Produkt verwendet werden, gibt es viele Geschichten und es ist einfach, weiterhin Artikel zu veröffentlichen. ――Es scheint mit dem Grad der Auswirkung von Funktionsänderungen aufgrund von Aktualisierungen in Zusammenhang zu stehen
** Klein λ: Kurze Überlebenszeit **
CentOS, Ubuntu, PostgreSQL, Nginx, Git, Slack usw.
Eindruck, dass Tools für Entwicklungsplattformen wie Betriebssystem und Middleware sowie Tools für Entwicklungsunterstützung wie Git und Slack konzentriert sind ―― Da es sich um einen grundlegenden Teil handelt, gibt es relativ wenig Material, sodass die Veröffentlichung von Artikeln in der Regel kurzfristig ist
** ρ ist groß: Die Steigung der Überlebensratenkurve wird mit der Zeit steiler **
SSH, Chrome, Git, Slack, Mac, Windows usw.
Eindruck, dass grundlegende Werkzeuge konzentriert sind
Viele Artikel, die sich auf grundlegende Tools beziehen, sind Einführungsartikel. Nach dem Start der Veröffentlichung wird die kontinuierliche Veröffentlichung noch eine Weile fortgesetzt, nimmt jedoch nach einer Weile ab.
** ρ ist klein: Die Steigung der Überlebensratenkurve wird im Laufe der Zeit sanfter **
Programmiersprache, Middleware, Linux-Betriebssystem usw.
Eindruck, dass relativ hochspezialisierte Werkzeuge (Techniken) konzentriert sind. ――Es ist einfach, Artikel mit hochspezialisierten Tools (Techniken) sofort nach dem Start zu veröffentlichen, aber einige Leute veröffentlichen weiterhin.
Es ist in der folgenden Abbildung zusammengefasst.
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:
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:
iOS V.S. Android
Emacs V.S. Vim
Recommended Posts