【问题标题】:value matching between two DataFrames using pandas in python在python中使用pandas在两个DataFrame之间进行值匹配
【发布时间】:2023-03-24 00:35:01
【问题描述】:

您好,我有两个如下所示的 DataFrame

 DF1

 Alpha   |  Numeric  |  Special

 and     |   1        |  @
 or      |   2       |  #
 lol ok  |   4       |  &






DF2 with single column

Content          

boy or girl  
school @ morn
pyc LoL ok student
Chandra

我想搜索 DF1 中的任何列是否有 DF2 的内容列中的任何关键字,并且输出应该在新的 DF 中

 `df11 = (df1.unstack()
      .reset_index(level=2,drop=True)
      .rename_axis(('col_order','col_name'))
      .dropna()
      .reset_index(name='val_low'))

 df22 = (df2['Content'].str.split(expand=True)
                 .stack()
                 .rename('val')
                 .reset_index(level=1,drop=True)
                 .rename_axis('idx')
                 .reset_index())`

 df22['val_low'] = df22['val'].str.lower()                    

 df = (pd.merge(df22, df11, on='val_low', how='left')
   .dropna(subset=['col_name'])
   .sort_values(['idx','col_order'])
   .drop_duplicates(['idx']))


 df = (pd.concat([df2, df.set_index('idx')], axis=1)
   .fillna({'col_name':'Other'})[['val','col_name','Content']])

但它没有考虑lol ok之间的空格

 expected_output_DF

     val      col_name          Content
 0   or       Alpha             boy or girl
 1    @      Special            school @ morn
 2   lol ok  Alpha              pyc LoL ok student
 3  NaN      Other              Chandra

有人帮我解决这个问题

【问题讨论】:

  • 抱歉,您的预期输出是什么?
  • output_DF 是我的预期输出
  • 如果可能请提出一个新的逻辑
  • 查看我们的任何一个答案,它们的作用基本相同。
  • 是的,当然@bharath,coldspeed (y)

标签: python pandas dataframe data-analysis


【解决方案1】:

融化数据框 1 并将其转换为 dict。然后根据数据帧2中模式匹配获得的键获取dict的值,即

vals = df.melt()
di = dict(zip(vals['value'],vals['variable']))
# {'or': 'Alpha', 1: 'Numeric', 2: 'Numeric', 'and': 'Alpha', 4: 'Numeric', '@': 'Special', '#': 'Special', '&': 'Special', 'Special': 'new', 'Alpha': 'new', 'lol ok': 'Alpha'}

#Create a regex pattern based on dict keys. 
pat = '|'.join(r"\s{}\s".format(x) for x in di.keys())

#Find the words that match the pattern 
df2['val'] = df2['Content'].str.lower().str.findall(pat).apply(lambda x : x[0].strip() if len(x)>=1 else np.nan)

# Map the values with di and fill nan with other. 
df2['new'] = df2['val'].map(di).fillna('other')

输出:

内容新值 0 男孩或女孩 Alpha 或 1 所学校@早上特别@ 2 pyc LoL ok 学生 Alpha lol ok 3 钱德拉其他 NaN

【讨论】:

  • 我无法融化我的数据框,我认为语法应该是pd.melt(df),您可以在解决方案中确认并编辑相同的内容
  • 我收到此错误,TypeError: object of type 'float' has no len() df2['val'] = df2[content_col].str.lower().str.findall(pat).apply(lambda x : x[0].strip() if len(x)>=1 else np.nan)
  • 你使用的是哪个熊猫版本?
  • pandas 版本是 '0.19.2' ,我做了 fillna() 但它以其他方式影响
  • 更新你的 pandas 版本再试一次
【解决方案2】:

使用str.cat + str.extract。然后,使用map 作为列名,并使用pd.concat 加入。

i = df.stack().astype(str)
j = i.reset_index(level=0, drop=1)

m = dict(zip(j.values, j.index))
v = i.str.cat(sep='|')  

df2['val'] = df2.Content.str.extract(r'\s(' + v + r')\s', flags=re.I, expand=False)
df2['col_name'] = df2['val'].str.lower().map(m).fillna('Other')

df2

              Content     val col_name
0         boy or girl      or    Alpha
1       school @ morn       @  Special
2  pyc LoL ok student  LoL ok    Alpha
3             Chandra     NaN    Other

详情

  • ij 是用于创建映射的设置变量
  • m 是值到列名的映射
  • v 是发送到str.extract 以进行关键字提取的正则表达式模式。我使用re.I 忽略此案
  • 我使用map + fillna 通过m 将提取的值映射到列名
v
'and|1|@|or|2|#|lol ok|4|&'

m
{'#': 'Special',
 '&': 'Special',
 '1': 'Numeric',
 '2': 'Numeric',
 '4': 'Numeric',
 '@': 'Special',
 'and': 'Alpha',
 'lol ok': 'Alpha',
 'or': 'Alpha'}


df['val']

0        or
1         @
2    LoL ok
3       NaN
Name: val, dtype: object

df['col_name']

0      Alpha
1    Special
2      Alpha
3      Other
Name: col_name, dtype: object

【讨论】:

  • @CHANDRAMURUGAN 检查我的答案的顶部,它就在那里。
  • @CHANDRAMURUGAN 只是让你知道......如果我们的答案之一有帮助,你应该accept it
  • @cᴏʟᴅsᴘᴇᴇᴅ 代码中有很多新术语。你需要更新它。我认为是df2['val'] =,也不是val.str,也许是df2['val'l.str
  • @Bharath 哦,伙计,有很多这样的错误,但我已经修复了。
  • 干杯,我也是 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-16
  • 1970-01-01
  • 2015-10-15
  • 2023-02-21
  • 1970-01-01
  • 2019-06-29
  • 1970-01-01
相关资源
最近更新 更多