如果字符串包含子字符串pyspark,则进行筛选

如果字符串包含子字符串pyspark,则进行筛选,pyspark,apache-spark-sql,Pyspark,Apache Spark Sql,我有两个数据集。在每一篇文章中,我都有几个专栏。但是我只想使用每个数据集中的两列,而不想在两个数据集之间进行任何连接、合并或组合。 示例数据集1: column_dataset_1 <String> | column_dataset_1_normalized <String> ----------------------------------------------------------------------- 11882621-V021BRP161

我有两个数据集。在每一篇文章中,我都有几个专栏。但是我只想使用每个数据集中的两列,而不想在两个数据集之间进行任何连接、合并或组合。

示例数据集1:

column_dataset_1 <String>    |      column_dataset_1_normalized <String>
-----------------------------------------------------------------------
11882621-V021BRP161305-1     |      11882621V021BRP1613051
-----------------------------------------------------------------------
W-B.7120RP1605794            |      WB7120RP1605794
-----------------------------------------------------------------------
D/57RP.1534421               |      D57RP1534421
-----------------------------------------------------------------------
125858G_022BR/P070751        |      125858G022BRP070751
-----------------------------------------------------------------------
300B.5190C57/51507           |      300B5190C5751507
-----------------------------------------------------------------------
有人可以给我提个建议我怎么做?
谢谢

连接两个数据帧的方法多种多样:

(1) 在使用SQL函数等规范化的列\u数据集\u 2\u中查找字符串列\u数据集\u 1\u的位置/位置,如果存在,则返回一个位置(基于1)

    from pyspark.sql.functions import expr

    cond1 = expr('locate(column_dataset_1_normalized,column_dataset_2_normalized)>0')
    cond2 = expr('instr(column_dataset_2_normalized,column_dataset_1_normalized)>0')
    cond3 = expr('position(column_dataset_1_normalized IN column_dataset_2_normalized)>0')
(2) 使用正则表达式从列\u数据集\u 2\u规格化查找列\u数据集\u 1\u规格化,这仅在列\u数据集\u 1\u规格化中未显示正则表达式元字符时有效

运行以下代码并使用上述条件之一,例如:

df1.join(df2, cond1).select('column_dataset_1').show(truncate=False)
+---------------------+
|column_dataset_1     |
+---------------------+
|W-B.7120RP1605794    |
|125858G_022BR/P070751|
+---------------------+
编辑:根据注释,匹配的子字符串可能与df1.column\u dataset\u 1不同,因此我们需要对规范化字符串中的子字符串进行反向工程。根据规范化的执行方式,下面的udf可能会有所帮助(请注意,这将不包括任何可能在匹配中的前导/尾随非alnum)。基本上,我们将按字符遍历字符串,并在原始字符串中找到规范化字符串的开始/结束索引,然后获取子字符串:

from pyspark.sql.functions import udf

@udf('string')
def find_matched(orig, normalized):
  n, d = ([], [])
  for i in range(len(orig)):
    if orig[i].isalnum(): 
      n.append(orig[i])
      d.append(i)
  idx = ''.join(n).find(normalized)
  return orig[d[idx]:d[idx+len(normalized)]] if idx >= 0 else None

df1.join(df2, cond3) \
   .withColumn('matched', find_matched('column_dataset_2', 'column_dataset_1_normalized')) \
   .select('column_dataset_2', 'matched', 'column_dataset_1_normalized') \
   .show(truncate=False)

+------------------------------------------------------------------------------------+-----------------------+---------------------------+
|column_dataset_2                                                                    |matched                |column_dataset_1_normalized|
+------------------------------------------------------------------------------------+-----------------------+---------------------------+
|Por ejemplo, si W-B.7120RP-1605794se trata de un archivo de texto,                  |W-B.7120RP-1605794     |WB7120RP1605794            |
|utilizados 125858G_022BR/P-070751 frecuentemente (por ejemplo, un texto que describe|125858G_022BR/P-070751 |125858G022BRP070751        |
+------------------------------------------------------------------------------------+-----------------------+---------------------------+

你为什么不想加入呢?这是你描述的问题的典型答案。你能详细说明一下你尝试了哪些无效的方法吗?@OliverW。谢谢你的回答。数据集之间没有公共列。出于这个原因,我提出了这个问题。我正试图找到我这边的解决办法。希望我能从您那里得到建议/帮助。
df1.join(df2,expr('column\u dataset\u 2\u normalized rlike column\u dataset\u 1\u normalized')。选择('column\u dataset\u 1')
@verojoucla,连接两个数据帧时不需要公共列。您还可以在连接条件中使用函数
instr(…)>0
。谢谢,我将测试它。但是我想从列\u dataset\u 2中提取引用的值,因为有时列\u dataset\u 2和列\u dataset\u 1是不同的。@verojoucla,只需将
column\u dataset\u 2
添加到select方法中,这就是您需要的吗
df.join(…)。选择('column\u dataset\u 1','column\u dataset\u 2')
BTW。出于测试目的,我在原始示例文本中添加了一些非alnum字符。@verojoucla,我想你已经有了答案。周末愉快。嗨,@verojoucla,由于日程安排,我不像去年那样经常上网。但我相信你可以从社区得到足够的帮助:)
    cond4 = expr('column_dataset_2_normalized rlike column_dataset_1_normalized')
df1.join(df2, cond1).select('column_dataset_1').show(truncate=False)
+---------------------+
|column_dataset_1     |
+---------------------+
|W-B.7120RP1605794    |
|125858G_022BR/P070751|
+---------------------+
from pyspark.sql.functions import udf

@udf('string')
def find_matched(orig, normalized):
  n, d = ([], [])
  for i in range(len(orig)):
    if orig[i].isalnum(): 
      n.append(orig[i])
      d.append(i)
  idx = ''.join(n).find(normalized)
  return orig[d[idx]:d[idx+len(normalized)]] if idx >= 0 else None

df1.join(df2, cond3) \
   .withColumn('matched', find_matched('column_dataset_2', 'column_dataset_1_normalized')) \
   .select('column_dataset_2', 'matched', 'column_dataset_1_normalized') \
   .show(truncate=False)

+------------------------------------------------------------------------------------+-----------------------+---------------------------+
|column_dataset_2                                                                    |matched                |column_dataset_1_normalized|
+------------------------------------------------------------------------------------+-----------------------+---------------------------+
|Por ejemplo, si W-B.7120RP-1605794se trata de un archivo de texto,                  |W-B.7120RP-1605794     |WB7120RP1605794            |
|utilizados 125858G_022BR/P-070751 frecuentemente (por ejemplo, un texto que describe|125858G_022BR/P-070751 |125858G022BRP070751        |
+------------------------------------------------------------------------------------+-----------------------+---------------------------+