将日期框架中列的值与 pandas 中其他数据框架的列值进行比较

Comparing values from column in date frame to column values from the other data frame in pandas

我有两个数据框,如果 df1 的第 "A" 列的值包含在 df2 的第 "B" 列的单元格中,我想将数据框 df2 的行插入到 df1。如果是这样,那么我想在 df1 中的 "A" 列的匹配值下方插入行。需要插入的行是根据 "Keyword" 列从 df2 中提取的,就像我从 "Keyword" 列中的一个 "test" 到下面的 "test" 行一样。 =18=]

这是数据框:

df1

    A      Keyword      B                  C
    m55                 m32\nm83\nm18      123
    m56                 m12                546
    m68
    m32
    m83
    m65
    m73                 m77\nm78           558
    m23
    m98
    m77
    m18
    m4
    m12
    m78

我有第二个数据框 (df2),我从中提取行并插入到 df1 中。我在 "Keyword".

列中提取从 "test" 到 "test" 的行

df2

     Keyword      Matches            C
     test         m32\nm83\nm18      123
     something
     something
     something
     test
     something
     something
     test         m12                546
     something
     test         m77\nm78           558
     test
     something

所以,最后我需要这个:

df1

      A         Keyword      B                  C
      m55                    m32\nm83\nm18      123
      m56                    m12                546
      m68
      m32
                test         m32\nm83\nm18      123
                something
                something
                something
      m83
                test         m32\nm83\nm18      123
                something
                something
                something
     m65
     m73                    m77\nm78           558
     m23
     m98
     m77
                test         m77\nm78           558
     m18
                test         m32\nm83\nm18      123
                something
                something
                something
     m4
     m12
                test         m12                546
                something
     m78
                test         m77\nm78           558

如何操作?

编辑:

首先我有这个功能:

def insert_row(idx, df, df_insert):
        return df.iloc[:idx, ].append(df_insert).append(df.iloc[idx:, ]).reset_index(drop = True)

然后我创建了从 df2 中提取行的函数:

def TestStepsReturn(df, SearchingElement):
        TestCaseList = df.index[df["Keyword"] == "test"].tolist()
        TestCaseList = np.asarray(TestCaseList)
        try:
            idx = TestCaseList[TestCaseList <= df.index[df["Matches"].str.contains(SearchingElement)][0]].max()
            idx = np.where(TestCaseList == idx)
            if idx[0][0]!=(len(TestCaseList)-1):
                return df.loc[TestCaseList[idx[0][0]]:TestCaseList[idx[0][0]+1]-1]
            return df.loc[TestCaseList[idx[0][0]]:]
        except:
            return pd.DataFrame(columns=df.columns)#return the empty data frame with the same columns names

然后我创建了另一个使用 TestStepsReturn 的:

 def SerchIDs(dfFidx, df1, df2, SearchingColumn):
        for feature in dfFidx:
            feature += i 
            df_new = TestStepsReturn(df2, df1.loc[feature, SearchingColumn])# 
            df1 = insert_row(feature+1, df1, df_new)
            i += int(df_new.size/len(df_new.columns.values))
        return df

然后我有代码:

dfFidx = df1.index
df1 = SerchIDs(dfFidx, df1, df2, "A")

如果具有 Matches 的第一行在 Keyword 列中也有值 test,则解决方案有效:

#groups for get cumulative sum with comparing test value and not missing values
df2['g1'] = df2['Keyword'].eq('test').cumsum()
df2['g2'] = df2['Matches'].notna().cumsum()
#get only first groups with test
df2 = df2[df2.groupby('g2')['g1'].transform('min') == df2['g1']]
#add index value from df1 with merge
df11 = df1.reset_index()[['index','B']].dropna().rename(columns={'B':'Matches', 'index':'idx'})
df2 = df2.merge(df11, on='Matches', how='left').drop(['g1','g2'], axis=1)
df2['idx'] = df2['idx'].ffill().astype(int)
print (df2)
     Keyword        Matches      C  idx
0       test  m32\nm83\nm18  123.0    0
1  something            NaN    NaN    0
2  something            NaN    NaN    0
3  something            NaN    NaN    0
4       test            m12  546.0    1
5  something            NaN    NaN    1
6       test       m77\nm78  558.0    6
#create dictionary of DataFrames - key is index of df1
d2 = dict(tuple(df2.groupby('idx')))
#print (d2)

d = df1['B'].dropna().to_dict()
d1 = {k: df1.index[df1['A'].str.contains("|".join(v.split("\n")))] for k, v in d.items()}

#in loop create new index and append to list
L = []
for k, v in d1.items():
    df = d2[k]
    for x in v:
        cum = np.cumsum(np.repeat(1, len(df)) / (len(df) + 1))
        df.index = np.repeat(x, len(df)) + cum
        L.append(df.copy())

#join all together
df = pd.concat([df1] + L).sort_index().reset_index(drop=True)

print (df)

      A              B      C    Keyword        Matches  idx
0   m55  m32\nm83\nm18  123.0        NaN            NaN  NaN
1   m56            m12  546.0        NaN            NaN  NaN
2   m68            NaN    NaN        NaN            NaN  NaN
3   m32            NaN    NaN        NaN            NaN  NaN
4   NaN            NaN  123.0       test  m32\nm83\nm18  0.0
5   NaN            NaN    NaN  something            NaN  0.0
6   NaN            NaN    NaN  something            NaN  0.0
7   NaN            NaN    NaN  something            NaN  0.0
8   m83            NaN    NaN        NaN            NaN  NaN
9   NaN            NaN  123.0       test  m32\nm83\nm18  0.0
10  NaN            NaN    NaN  something            NaN  0.0
11  NaN            NaN    NaN  something            NaN  0.0
12  NaN            NaN    NaN  something            NaN  0.0
13  m65            NaN    NaN        NaN            NaN  NaN
14  m73       m77\nm78  558.0        NaN            NaN  NaN
15  m23            NaN    NaN        NaN            NaN  NaN
16  m98            NaN    NaN        NaN            NaN  NaN
17  m77            NaN    NaN        NaN            NaN  NaN
18  NaN            NaN  558.0       test       m77\nm78  6.0
19  m18            NaN    NaN        NaN            NaN  NaN
20  NaN            NaN  123.0       test  m32\nm83\nm18  0.0
21  NaN            NaN    NaN  something            NaN  0.0
22  NaN            NaN    NaN  something            NaN  0.0
23  NaN            NaN    NaN  something            NaN  0.0
24   m4            NaN    NaN        NaN            NaN  NaN
25  m12            NaN    NaN        NaN            NaN  NaN
26  NaN            NaN  546.0       test            m12  1.0
27  NaN            NaN    NaN  something            NaN  1.0
28  m78            NaN    NaN        NaN            NaN  NaN
29  NaN            NaN  558.0       test       m77\nm78  6.0