Сравнение значений из столбца в фрейме даты со значениями столбца из другого фрейма данных в пандах - PullRequest
0 голосов
/ 20 декабря 2018

У меня есть два фрейма данных, и я хочу вставить строки из фрейма данных df2 в df1, если значение из столбца «A» в df1 содержится в ячейке столбца «B» в df2.Если это так, то я хочу вставить строки ниже соответствующего значения из столбца «A» в df1.Строки, которые необходимо вставить, извлекаются из df2 на основе столбца «Ключевое слово» таким образом, что у меня есть строки от одного «теста» в столбце «Ключевое слово» до следующего «теста».

Это данныеframe:

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.Я извлекаю строки из «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")

1 Ответ

0 голосов
/ 20 декабря 2018

Решение работает, если первая строка с Matches также имеет значение test в столбце Keyword:

#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
...