【问题标题】:python dataframe replace partial strings in a column based on other column's conditionpython数据框根据其他列条件替换列中的部分字符串
【发布时间】:2018-08-01 18:51:07
【问题描述】:

Dataframe点击看截图,因为我是新来的,我需要10个声望才能嵌入图片

Expected result

数据框是从 csv 文件导入的。 “类型”和“主题”是项目的属性。 “标签”是一个长字符串列,包含每个项目的混合(随机排序)标签(由“,”分隔)。基本上我需要做的是检查'Tags'列中是否有正确的主题标签(col_{theme}),如果没有,将其添加到'Tags'列。

例如:

item 8: 'Tags' 列有一个'col_t3',它的主题是't3'。所以这是正确的,我们通过了。

item 1: 'Tags' 列中有一个 'col_t1',但它的实际主题是 't2',所以我需要将 'col_t1' 替换为 'col_t2' 并保持同一列中的其他标签不变

item 2 和 item 5:'Tags' 列中没有 'col_{theme}' 标签,所以我分别在它们的 'Tags' 列中添加了 add 'col_t1' 和 'col_t5'。

请帮忙!!

【问题讨论】:

  • 你能帮我显示截图吗?该帖子仅显示链接。我是新来的,谢谢!
  • CTRL + G 然后 CTRL + V... 或使用字段上方的工具。
  • 我做到了,我现在知道为什么了。它说因为我是新来的,需要 10 个声望点来嵌入图片。真可惜。
  • 很高兴知道。如果有人摆脱了你在这个问题上的其他负面观点并且你得到 +1,你就会在那里。我只能投一票。
  • @Ray,请不要使用图像,因为这会使其他人更难复制您的数据。请尽可能粘贴原始数据。

标签: python string pandas dataframe conditional-statements


【解决方案1】:

这模拟了您在屏幕截图中显示的输入:

import pandas as pd
import numpy as np

df = pd.DataFrame({"type": ["a", "c", "d", "a", "b", "a", "a", "c"], 
                  "tags": ["col_t1, col_red, large", np.nan, "col_t2, col_black, small", 
                           "col_t4, large, col_yellow", "col_gold, col_fancy,", "col_t1, thick, col_k",
                          np.nan, "col_t3, fancy, red"],
                  "theme": ["t2", "t1", "t2", "t3", "t2", "t1", np.nan, "t3"]})

df.set_index(np.arange(1, len(df)+1), inplace=True)
print df

输出:

                      tags theme type
1     col_t1, col_red, large    t2    a
2                        NaN    t1    c
3   col_t2, col_black, small    t2    d
4  col_t4, large, col_yellow    t3    a
5       col_gold, col_fancy,    t2    b
6       col_t1, thick, col_k    t1    a
7                        NaN   NaN    a
8         col_t3, fancy, red    t3    c

产生所需输出的代码:

prefix = "col_"

# Iterate over rows with non-empty theme
for row in df[df["theme"].notnull()].itertuples():

    if pd.isnull(row.tags):
        # Replace NaN in tags column with a single tag from theme column 
        df.loc[row.Index, "tags"] = prefix + row.theme
    else:
        # Extract existing tags with prefix
        inferred_tags = [t.replace(prefix, "") for t in row.tags.split(",") if prefix in t] 

        if row.theme not in inferred_tags:
            df.loc[row.Index, "tags"] = row.tags.rstrip(" ,") + ", " + prefix + row.theme     
print df

输出:

                                tags theme type
1     col_t1, col_red, large, col_t2    t2    a
2                             col_t1    t1    c
3           col_t2, col_black, small    t2    d
4  col_t4, large, col_yellow, col_t3    t3    a
5        col_gold, col_fancy, col_t2    t2    b
6               col_t1, thick, col_k    t1    a
7                                NaN   NaN    a
8                 col_t3, fancy, red    t3    c

希望这是您正在寻找的。据称itertuples() 迭代所有行比iterrows() 更快。另外,请记住,我使用 numpy 和特别是 np.nan 在您的输入中模拟 NaN,但如果您的数据来自 csv,则不需要 numpy。

--- 更新 ---

如 cmets 中所述,代码应替换与主题匹配的标签。这是更新的解决方案:

prefix = "col_"

# Find all unique themes (notnull() excludes nan from the list)
themes = df[df["theme"].notnull()]["theme"].unique()

# Add prefex to all themes for comparison with tags; convert to set 
prefixed_themes = set([prefix + t for t in themes])

# Iterate over rows with non-empty theme
for row in df[df["theme"].notnull()].itertuples():

    if pd.isnull(row.tags):
        # Replace NaN in tags column with a single tag from theme column 
        df.loc[row.Index, "tags"] = prefix + row.theme
    else:
        # Extract existing tags with prefix (do not remove prefix; remove all spaces)
        inferred_tags = row.tags.replace(" ", "").split(",")

        # Use sets to check if there is any intersection between tags and themes
        if len(set(inferred_tags).intersection(prefixed_themes)) > 0:

            # Iterate over inferred_tags to find and replace matches with themes 
            for idx, t in enumerate(inferred_tags):
                if t in prefixed_themes:
                    inferred_tags[idx] = prefix + row.theme

            df.loc[row.Index, "tags"] = ", ".join(inferred_tags) 
        else:
            # In this case, add theme to tags (no replacement)
            df.loc[row.Index, "tags"] = row.tags.rstrip(" ,") + ", " + prefix + row.theme 

print df

输出:

                                tags theme type
1             col_t2, col_red, large    t2    a
2                             col_t1    t1    c
3           col_t2, col_black, small    t2    d
4  col_t4, large, col_yellow, col_t3    t3    a
5        col_gold, col_fancy, col_t2    t2    b
6               col_t1, thick, col_k    t1    a
7                                NaN   NaN    a
8                 col_t3, fancy, red    t3    c

请注意,代码会根据主题列中存在的所有值检查标签(添加前缀);如果某个值(如 t4)不在主题列中,则它不被视为合法主题标签,因此在处理期间不会替换第 4 项中的 col_t4。如果您需要替换所有col_t*,则需要具体说明。希望这是一个有用的解决方案,您可以从这里获得它。

【讨论】:

  • 很好,但有一个缺陷。您的解决方案几乎就是我想要的。唯一不正确的一件事是您没有替换不正确的标签。例如,项目 1 有 'col_t1',而它的实际是 't2',所以当你将 'col_t2' 添加到项目 1 的标签列时,'col_t1' 应该被替换或删除。但我认为您只需要对代码进行一点更改。 (待续……)
  • 我做的是使用正则表达式,(原始数据字符串比较复杂)但是我更喜欢你的解决方案,下次编辑数据时我会尝试使用你的方法。谢谢你 。顺便说一句,如果你明白我所说的,你能更新你的解决方案吗?欣赏
  • 好的,我明白了。标签的顺序是否重要(它们可以重新排列,例如,使 col_ 标签在出现时排在第一个或最后一个)?此外,每行标签中是否最多有 1 个 col_ (其中 来自主题列),或者可能有更多?最后,可以假设它总是 col_tX(其中 t 总是存在,X 是一个数字)或者主题可以有不同的格式?
  • 检查上面的更新解决方案。在那里,标签的顺序被保留。标签被替换,除了那些不在主题列中的标签,如末尾评论中所述。
  • 顺序无关紧要。在 Tags 中始终是 col_tX。你做得很好!
猜你喜欢
  • 2020-05-29
  • 2023-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多