作者出版頻率條形競賽圖

作者出版頻率條形競賽圖

為了演示《周報》作者出版頻率的走勢,我們利用了條形競賽圖。傳統的棒形圖會將數據在一個圖表中固定地顯示出來,讓讀者仔細閱讀,而條形競賽圖則是動態棒形圖,把連串的數據連續顯示出來。


圖一的條形競賽圖演示每年於《周報》中出版頻率最高首二十位作者的出版走勢 (1967年除外),此視覺演示除了讓讀者了解當年筆者的產量和發展,更可了解橫跨二十二年來多產作者的轉變和走勢。當代的作家會使用不同的筆名在不同的刊物和專欄投稿,條形競賽圖亦顯示不同筆名在不同年代的出現。

《中國學生周報》的作者出版頻率(首20位)

圖一:《中國學生周報》的作者出版頻率(首20位)條形競賽圖

由圖一可見,《周報》在五十年代刊印初期,一些較多產的作家有崑南、黃思騁和麥菁。在五十年代後期,作家如小慶、但尼、藍子和張愛倫開始冒起頭來。多產作家小慶在六、七十年代繼續投稿,在六十年代初期她使用了筆名小離,之後則主要使用為人熟識的筆名陸離。藍子和張愛倫是作家西西的其中兩個筆名,在六十年代後期,除了筆名西西,她亦用筆名南南來出版。作家小思在六十年代中期之後十分活躍,除筆名小思,她亦常用筆名明川來投稿。《周報》出版的最後一年(即1974年),本名梁秉鈞和他的筆名也斯在圖表中都位於很高的位置。

圖一的條形競賽圖除了演示作家的不同筆名,亦讓我們認識《周報》中一些重要的體裁。其中一種體裁是影評,但尼和陸離都是當代重要的影評家,他們的名字都在相關五、六十年代的圖表中出現,在圖表中亦可見到其他的影評家,包括羅卡、石琪和吳昊。除了中文的文章,《周報》亦有一些英語的文章,在六十年代初「花生漫畫」開始在《周報》中刊印,作者舒爾茨在 1961 至 1964 年的圖表中緊守着首位。

製作條形競賽圖的方法

製作條形競賽圖只需要把每一年的數據在如圖二的圖表表列出來,然後放進製作競賽棒形圖的工具,競賽棒形圖就會呈現於眼前。

圖二:《中國學生周報》的作者出版頻率統計圖表(節錄)

由於我們製作的是《周報》的作者出版頻率條形競賽圖,我們需要作者出版頻率的數據。我們首先收集了在香港文學資料庫《周報》元數據內作者欄目的數據,資料庫有 79,975 條《周報》的記錄,其中 53,374 條的作者欄目是有資料的。這些資料記錄了每一篇文章的責任者,很多都附有責任的類別,如訪問、文、翻譯、圖等,在電腦程式語言中,由於這些詞語不是被分析的數據用詞,因而被稱為停用詞。我們在作者欄目的資料中刪除這些停用詞, 並使用 OpenRefine 做數據清潔。

有些作者欄目包含了多於一個作者的名稱,因此我們利用函式 def create_full_name_list,採集所有作者的名稱,共 55,506 個,這包括了 18,804 個獨立不重覆的名稱,再作一次數據清潔。因為我們仍在試驗性階段,加上停用詞和作者的名稱比較多變,所以我們仍在改良名稱採集的技巧和數據清潔的過程,而已採集的名稱並未作嚴謹的權威管理。

在得到所有作者名稱之後,我們利用函式 def search_yeardef generate_data_for_year 把每一年作者出版的數量作統計,製作了如圖二的數據圖表。雖然有些作者以不同的筆名出版文章,但是圖一的條形競賽圖是以每一個筆名作獨立統計。由於作者名稱包括一些廣告持份者,而他們刊登廣告量很高,我們利用這數據圖表時若是演示高產量的作家,就需要先把一些不適合用作演示的名稱及其相關數據取走,再把數據圖表放進製作競賽棒形圖的工具(如 flourish.studio),圖一的競賽棒形圖就會出現了。

我們亦利用了 Python 的 plotly library 製作了傳統的棒形圖來演示《周報》的作者出版頻率,除了可以把同一作者不同筆名的統計數字獨立地或加起來演示,並可供選擇演示不同年份及排名範圍,這互動的棒形圖將會在圖書館的其他平台供大家使用。

電腦程式

以下的電腦程式(Python 3.7),可以用作準備作者頻率統計圖表。

# -*- coding: utf-8 -*-
import pandas as pd

# Get a list with all names
def create_full_name_list():
    author_data = pd.read_csv('weekly_metadata.csv')        
    full_name_list = list(author_data['column_name_author_name_after_removing_stopword'])
    full_name_list = list(set(full_name_list))
    return full_name_list

# Get the first and last year in the dataset
def search_year():
    data = pd.read_csv('weekly_metadata.csv')
    date_list = list(set((list(data['column_name_search_date']))))
    date_list = [str(x) for x in date_list if str(x) != 'nan']
    yearList = []
    # Get the year from the date
    for i in range(0,len(date_list)):
        yearList.append(date_list[i][(date_list[i].rfind('/')) + 1 :])    
    yearList = list(set(yearList))
    yearList.sort(reverse = False)
    first_year = yearList[0]
    last_year = yearList[-1]
    return first_year, last_year, yearList

# Count the frequency of each name in a year
def generate_data_for_year(year, name_list):
    data = pd.read_csv('weekly_metadata.csv')
    year_str = str(year)
    temp_data = data[data['column_name_search_date'].str.contains(year_str, na = False)]
    name_list_from_temp_df = list(temp_data['column_name_author_name_after_removing_stopword'])
    temp_dict = {}
    temp_count = []
    # Count the frequency of each element
    for i in range(0, len(name_list)):       
        count = 0
        for element in name_list_from_temp_df:
                if str(element) == name_list[i] and str(element) !='nan':
                    count = count + 1
        temp_count.append(count)
    return temp_count
# create full name list
data = {}
full_name_list = create_full_name_list()
cat_list = []
# Assign the name to different categories for differnet color
for i in range(0, len(full_name_list)):    
    cat_list.append(i % 50)
data['Name'] = full_name_list
data['cat'] = cat_list
# generate the data for each year
first_year, last_year, yearList = search_year()
# Get the count for each name in each year
for year in yearList:  
    current_year_count = generate_data_for_year(year, full_name_list)
    data[year] = current_year_count
# generate csv and xlsx files
df = pd.DataFrame.from_dict(data)
df.to_csv('data_for_bar_chart_race.csv', encoding = 'utf-8', index = False)
df.to_excel('data_for_bar_chart_race.xlsx', encoding = 'utf-8', index = False)