我有两个数据帧,并且如果df2的“ B”列的单元格中包含df1的“ A”列中的值,我想从数据帧df2到df1插入行。如果是这种情况,那么我想在df1中的“ A”列中的匹配值下方插入行。从df2基于“关键字”列中提取需要插入的行,方法是从“关键字”列中的一个“测试”到以下“测试”具有行。
这是数据帧:
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。我正在提取“关键字”列中从“测试”到“测试”的行。
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")
答案 0 :(得分:1)
如果在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