【问题标题】:Remove Words Less Than 4 Characters from Pandas Series从 Pandas 系列中删除少于 4 个字符的单词
【发布时间】:2023-03-06 17:12:02
【问题描述】:

我正在尝试从 Pandas 系列中的每个标量值中删除所有少于 4 个字符的单词。最好的方法是什么?这是我失败的尝试:

df['text'] = df['text'].str.join(word for word in df['text'].str.split() if len(word)>3)

我收到以下错误消息:

AttributeError: 'generator' 对象没有属性 'join'

我在这篇文章中的尝试基于字符串中的相同内容:Remove small words using Python

旁注:如果在删除前用少于 4 个字符标记我的话更好,请告诉我。

编辑:每个标量值都包含句子,所以我想删除值中长度小于 4 的任何单词。

【问题讨论】:

  • 我会考虑接受@piRSquared 的解决方案。我觉得这更“恐慌”。不过,进行一些性能比较会很有趣,让最快的获胜!

标签: python pandas parsing nlp


【解决方案1】:

使用带有.str.findall.str.join 的正则表达式似乎是最快的:

df['text'].str.findall('\w{4,}').str.join(' ')

时间

使用以下设置:

df = pd.DataFrame({'text':["The quick brown fox", "jumped over the lazy dog", "foo bar baz", 'words exceeding desired length']})
df = pd.concat([df]*10**4, ignore_index=True)

def pir2(df):
    t = df.text.str.split(expand=True).stack()
    return t.loc[t.str.len() >= 4].groupby(level=0).apply(' '.join)

我得到以下时间:

%timeit df['text'].str.findall('\w{4,}').str.join(' ')
10 loops, best of 3: 44.8 ms per loop

%timeit df.text.apply(lambda i: ' '.join(filter(lambda j: len(j) > 3, i.split())))
10 loops, best of 3: 79.3 ms per loop

%timeit df['text'].str.split().map(lambda sl: " ".join(s for s in sl if len(s) > 3))
10 loops, best of 3: 87.2 ms per loop

%timeit pir2(df)
1 loop, best of 3: 2.87 s per loop

【讨论】:

    【解决方案2】:

    你可以这样做:

    >>> df = pd.DataFrame({'text':["The quick brown fox", "jumped over the lazy dog"]})
    >>> df
                           text
    0       The quick brown fox
    1  jumped over the lazy dog
    >>> df['text'].str.split().map(lambda sl: " ".join(s for s in sl if len(s) > 3))
    0         quick brown
    1    jumped over lazy
    Name: text, dtype: object
    

    但老实说,我通常坚持使用 vanilla python 来进行文本处理管道。 pandas 数据结构不能很好地处理文本。至少,您正在失去numpy/pandas 的内存/速度优势。

    【讨论】:

    • 打败我 :-) +1
    【解决方案3】:

    考虑@juanpa.arrivillaga 的dataframe df

    df = pd.DataFrame({'text':["The quick brown fox", "jumped over the lazy dog"]})
    

    那么我们可以

    t = df.text.str.split(expand=True).stack()
    t.loc[t.str.len() >= 4].groupby(level=0).apply(' '.join)
    
    0         quick brown
    1    jumped over lazy
    dtype: object
    

    【讨论】:

    • 非常好,不过,您必须使用apply :(。我仍然认为pandas 是文本预处理的错误工具。
    • @juanpa.arrivillaga 你有什么建议?
    • 香草蟒。一旦你有了一个object dtype 的数据框,你就放弃了numpy/pandas 的速度/内存效率。有时这没关系,因为“面板”抽象仍然有用,并且pandas 数据结构中内置了许多方便的例程,但对于文本来说确实不是这样。我的大部分文本预处理都发生在普通 Python 中,通常会导致一些稀疏表示,我将这些表示输入sklearn 矢量化器以获得特征化的稀疏numpy 数组。但是如果我要使用pandas,我会选择这个:)
    • 哦,我总是忘记 expand 参数到 pandas 拆分方法!
    • @juanpa.arrivillaga 容易做;-)
    【解决方案4】:

    试试

    df.test.apply(lambda i: ' '.join(filter(lambda j: len(j) > 3, i.split())))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-17
      相关资源
      最近更新 更多