如何规范化Pandas数据框中列的列表文本?

1 投票
1 回答
2479 浏览
提问于 2025-04-18 16:41

基本上,我有一个关于Ike三明治的数据表,这个表有三列:配料 / 名称 / 价格,而配料这一列是一个配料列表,比如['x',' y',' z']。

不幸的是,当我抓取这个列表时,里面保留了一些奇怪的空格和其他格式问题,现在我想修改配料列,去掉空格并把字母都变成小写。

举个例子:

0    [Avocado, French Dressing, Gouda, Ham, Sal...   Al Bundy    $9.99
1    [Caesar, Halal Chicken, Marinated Artichoke ...     Backstabber     $9.99
2    [Bacon, Swiss, Turkey]  Barry B.    $8.98
3    [Avocado, Havarti, Turkey]  Barry Z.    $8.98
4    [Avocado, Halal Chicken, Honey Mustard, Pep...  Bella   $9.99

问题是:

> [x for x in mdf.ingredients[3:4]]
[[u'Avocado', u' Havarti', u' Turkey']]

注意到那些空格了吗?

我尝试过这样做:

for sandwich in mdf.ingredients:
    for ingredient in sandwich:
        ingredient = ingredient.strip()
        ingredient = ingredient.lower()

如果我在循环中打印配料,这样可以达到我的目标,但实际上并没有改变数据表中的值。

有没有办法直接修改这些列表里的值,还是说我需要新建一列来放这些修正过的值呢?

1 个回答

1

要修改 df['ingredients'],你可以把它赋值为一个列表的列表。比如,如果 df 看起来像这样:

import pandas as pd

df = pd.DataFrame([([u'Avocado', u' Havarti', u' Turkey'], 'Barry Z', 8.98),
                   ([u'Bacon', u' Swiss', u'Turkey'], 'Barry B', 8.98)],
                  columns=['ingredients', 'name', 'price'])

print(df)
#                     ingredients     name  price
# 0  [Avocado,  Havarti,  Turkey]  Barry Z   8.98
# 1      [Bacon,  Swiss,  Turkey]  Barry B   8.98

那么

df['ingredients'] = [[item.strip().lower() for item in lst] for lst in df['ingredients']]

会让 df 看起来像这样

                  ingredients     name  price
0  [avocado, havarti, turkey]  Barry Z   8.98
1      [bacon, swiss, turkey]  Barry B   8.98

不过,拥有一个包含列表的列通常不是很方便。如果你想找出所有含有瑞士奶酪的项目,你就得逐行检查,看看每一行是否有瑞士奶酪,然后返回那一行。

如果你把数据框(DataFrame)规范化,让每个项目都有自己的列,那么这种搜索就会简单很多。

例如:

import pandas as pd

df = pd.DataFrame([([u'Avocado', u' Havarti', u' Turkey'], 'Barry Z', 8.98),
                   ([u'Bacon', u' Swiss', u'Turkey'], 'Barry B', 8.98)],
                  columns=['ingredients', 'name', 'price'])

ingredients = df['ingredients'].apply(
    lambda lst: pd.Series(True, index=[item.strip().lower() for item in lst]))
ingredients.fillna(False, inplace=True)
del df['ingredients']
df = df.join(ingredients)
print(df)

会生成一个看起来像这样的数据框

      name  price avocado  bacon havarti  swiss turkey
0  Barry Z   8.98    True  False    True  False   True
1  Barry B   8.98   False   True   False   True   True

现在,要找出所有包含瑞士奶酪的项目,你可以使用:

In [43]: df[df['swiss']]
Out[43]: 
      name  price avocado bacon havarti swiss turkey
1  Barry B   8.98   False  True   False  True   True

顺便说一下,这段代码:

for ingredient in sandwich:
    ingredient = ingredient.strip()

不会影响 sandwich,因为在循环内部,变量 ingredient 被重新赋值为一个新值。这并不会改变 sandwich 中的值。理解这一点是理解 Python 的命名/引用模型 的基本要素。

撰写回答