【问题标题】:Pandas: Create a new column with coulmn name and cell of matching stringPandas:使用列名和匹配字符串的单元格创建一个新列
【发布时间】:2021-09-26 23:52:12
【问题描述】:

我正在搜索一个包含 300 列和超过 20 万行的大型电子表格。我想创建一个具有列标题和匹配单元格值的列。一些看起来像“列||值”的东西。我有搜索词和加入聚合器。我可以获得行索引名称,但我正在努力获取匹配的列和特定的单元格。到目前为止,这是我的代码

df = pd.read_excel (r"Test_file")

mask = df.astype(str).applymap(lambda x: any(y in x for y in ['Chann','Midm'])).any(1)

df['extract'] = df.loc[mask] #This only give me the index name. I would like the actual matched cell contents.

df['extract2'] = Column name

df['Match'] = df[['extract', 'extract2']].agg('||'.join.axis=1)

df.drop(['extract', 'extract2'], axis=1)

最终输出应该类似于 Output

【问题讨论】:

  • 你能显示你想要的输出吗?

标签: python pandas multiple-columns


【解决方案1】:

您可以先为特定列创建一个掩码(我稍微编辑了您的第二行),然后创建一个新的“匹配”列,其中所有值都初始化为“不匹配”,最后,将值更改为您想要的应用掩码后返回的行的格式(“列||值”)。我在以下示例代码中实现了这一点:

def match_column(df, column_name):
    column_mask = df.astype(str).applymap(lambda x: any(y in x for y in ['Chann','Midm']))[column_name]
    df['Match'] = 'No Match'
    df.loc[column_mask, 'Match'] = column_name + ' || ' + df[column_name]
    return df

df = {
    'Segment': ['Government', 'Government', 'Midmarket', 'Midmarket', 'Government', 'Channel Partners'],
    'Country': ['Canada', 'Germany', 'France', 'Canada', 'France', 'France']
}
df = pd.DataFrame(df)
display(df)

df = match_column(df, 'Segment')
display(df)

输出:

但是,这仅适用于单个列。我不知道在多列中有匹配项的情况下您想要什么输出(如果可以,请指定)。

更新:

如果您想使用列列表作为输入并与第一个实例匹配,您可以改用它:

def match_first_column(df, column_list): 
    df['Match'] = 'No Match'
    # iterate over rows
    for index, row in df.iterrows():
        # iterate over column names
        for column_name in column_list:
            column_value = row[column_name]
            substrings = ['Chann', 'Midm', 'Fran']
            # if a match is found
            if any(x in column_value for x in substrings):
                # add match string
                df.loc[index, 'Match'] = column_name + ' || ' + column_value
                # stop iterating and move to next row
                break
    return df

df = {
    'Segment': ['Government', 'Government', 'Midmarket', 'Midmarket', 'Government', 'Channel Partners'],
    'Country': ['Canada', 'Germany', 'France', 'Canada', 'France', 'France']
}
df = pd.DataFrame(df)
display(df)

column_list= df.columns.tolist() 
match_first_column(df, column_list)

输出:

【讨论】:

  • 谢谢。这很棒,但我正在尝试搜索整个数据框并获取第一个匹配实例。我试图通过将 column_name 设置为列列表来编辑您的代码,但出现错误:'can only concatenate list (not "str") to list'
  • def match_column(df, column_name): column_mask = df.astype(str).applymap(lambda x: any(y in x for y in ['Chann','Midm']))[ column_name] df['Match'] = '不匹配' df.loc[column_mask, 'Match'] = column_name + ' || ' + df[column_name] return df column_name = df.columns.tolist() match_column(df, column_name)
  • 我为列列表添加了一个新的编辑函数并获得了第一个匹配项。看看它是否适合你。 :)
  • 哇!谢谢你。这正是我想要做的。并感谢您的解释
【解决方案2】:

你可以试试:

mask = df.astype(str).applymap(lambda x: any(y in x for y in ['Chann','Midm'])).any(1)
df.loc[mask, 'Match'] = '||'.join(df[['extract', 'extract2']])
df['Match'].fillna('No Match', inplace=True)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-06
    • 2022-07-06
    • 2019-06-13
    • 2022-08-14
    • 1970-01-01
    • 2019-07-31
    • 2019-11-29
    相关资源
    最近更新 更多