簡體   English   中英

使用字典計算python數據幀中的字頻率

[英]Using dictionaries to count word frequency in python dataframe

我有一個由文本作業描述和3個空列組成的數據框

   index   job_description                 level_1      level_2        level_3
    0      this job requires masters in..    0             0              0
    1      bachelor degree needed for..      0             0              0
    2      ms is preferred or phd..          0             0              0

我正在嘗試瀏覽每個作業描述字符串並計算作業描述中提到的每個學位級別的頻率。 示例輸出應如下所示。

   index   job_description                 level_1      level_2        level_3
    0      this job requires masters in..    0             1              0
    1      bachelor degree needed for..      1             0              0
    2      ms is preferred or phd..          0             1              1

我創建了字典以進行比較,如下所示,但我對如何在數據框“作業描述”列的字符串中查找這些單詞並根據單詞是否存在填充數據框列有點無能為力。

my_dict_1 = dict.fromkeys(['bachelors', 'bachelor', 'ba','science
                           degree','bs','engineering degree'], 1)
my_dict_2 = dict.fromkeys(['masters', 'ms', 'master'], 1)
my_dict_3 = dict.fromkeys(['phd','p.h.d'], 1)

我非常感謝對此的支持..

這樣的事怎么樣?

由於您的三個詞典中的每一個都對應於您要創建的不同列,因此我們可以創建另一個字典映射,其中即將成為列的名稱作為鍵,並且在每個特定級別搜索的字符串作為值(實際上,您甚至不需要用於存儲my_dict_<x>項目的字典 - 您可以使用set - 但這不是一個大問題:

>>> lookup = {'level_1': my_dict_1, 'level_2': my_dict_2, 'level_3': my_dict_3}
>>> lookup
{'level_1': {'bachelors': 1, 'bachelor': 1, 'ba': 1, 'science degree': 1, 'bs': 1, 'engineering degree': 1}, 'level_2': {'masters': 1, 'ms': 1, 'master': 1}, 'level_3': {'phd': 1, 'p.h.d': 1}}

然后,遍歷您剛創建的字典中的每個建議列,並分配一個新列,用於創建所需的輸出,檢查每個my_dict_<x>對象中指定的每個級別,是否至少有一個屬於每行的作業描述。 ..

>>> for level, values in lookup.items():
...     df[level] = df['job_description'].apply(lambda x: 1 if any(v in x for v in values) else 0)
... 
>>> df
              job_description  level_1  level_2  level_3
0     masters degree required        0        1        0
1  bachelor's degree required        1        0        0
2    bachelor degree required        1        0        0
3                phd required        0        0        1

另一種解決方案,使用scikit-learn的CountVectorizer類,它計算字符串中出現的標記(基本上是單詞)的頻率:

>>> from sklearn.feature_extraction.text import CountVectorizer

指定特定詞匯 - 忘記所有其他不是“學術證書”關鍵詞的詞:

>>> vec = CountVectorizer(vocabulary={value for level, values in lookup.items() for value in values})
>>> vec.vocabulary
{'master', 'p.h.d', 'ba', 'ms', 'engineering degree', 'masters', 'phd', 'bachelor', 'bachelors', 'bs', 'science degree'}

使變換器適合文本可迭代, df['job_description']

>>> result = vec.fit_transform(df['job_description'])

深入了解結果:

>>> pd.DataFrame(result.toarray(), columns=vec.get_feature_names())
   ba  bachelor  bachelors  bs  engineering degree  master  masters  ms  p.h.d  phd  science degree
0   0         0          0   0                   0       0        1   0      0    0               0
1   0         1          0   0                   0       0        0   0      0    0               0
2   0         1          0   0                   0       0        0   0      0    0               0
3   0         0          0   0                   0       0        0   0      0    1               0

如果你想回到你的level_<x>列結構,最后一種方法可能需要更多的工作,但我想我只是將它顯示為一種考慮編碼這些數據點的不同方式。

稍微不同的方法是將關鍵字和作業描述存儲為集合,然后計算集合交叉點。 您可以通過向量化set.intersection緊湊地生成交集矩陣:

import pandas as pd

df = pd.read_csv(
    pd.compat.StringIO(
        """   index   job_description                 level_1      level_2        level_3
        0      this job requires masters in..    0             0              0
            1      bachelor degree needed for..      0             0              0
                2      ms is preferred or phd ..          0             0              0"""
    ),
    sep=r"  +",
)


levels = pd.np.array(
    [
        {"bachelors", "bachelor", "ba", "science degree", "bs", "engineering degree"},
        {"masters", "ms", "master"},
        {"phd", "p.h.d"},
    ]
)

df[["level_1", "level_2", "level_3"]] = (
    pd.np.vectorize(set.intersection)(
        df.job_description.str.split().apply(set).values[:, None], levels
    )
    .astype(bool)
    .astype(int)
)

   index                 job_description  level_1  level_2  level_3
0      0  this job requires masters in..        0        1        0
1      1    bachelor degree needed for..        1        0        0
2      2       ms is preferred or phd ..        0        1        1

我想我們可以這樣做:

# create a level based mapper dict
mapper = {'level_1':['bachelors', 'bachelor', 'ba','science degree','bs','engineering degree'],
          'level_2': ['masters', 'ms', 'master'],
          'level_3': ['phd','p.h.d']}

# convert list to set
mapper = {k:set(v) for k,v in mapper.items}

# remove dots from description
df['description'] = df['description'].str.replace('.','')

# check if any word of description is available in the mapper dict
df['flag'] = df['description'].str.split(' ').apply(set).apply(lambda x: [k for k,v in mapper.items() if any([y for y in x if y in v])])

# convert the list into new rows
df1 = df.set_index(['index','description'])['flag'].apply(pd.Series).stack().reset_index().drop('level_2', axis=1)
df1.rename(columns={0:'flag'}, inplace=True)

# add a flag column , this value will be use as filler
df1['val'] = 1

# convert the data into wide format
df1 = df1.set_index(['index','description','flag'])['val'].unstack(fill_value=0).reset_index()
df1.columns.name = None

print(df1)

   index                   description  level_1  level_2  level_3
0      0  this job requires masters in        0        1        0
1      1  bachelor degree needed for 0        1        0        0
2      2        ms is preferred or phd        0        1        1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM