![](/img/trans.png)
[英]In a Pandas dataframe, how to filter a set of rows based on a start row and end row both satisfying different conditions?
[英]Pandas How to create a new dataframe with a start and end even if on different rows
我有一个包含2列的pandas数据帧。 一些MessageID's
在它们以NewMessageID
开头的同一行MessageID's
结束,就像在下面的索引行0中一样。 但是像索引行2这样的其他人直到索引第4行才结束。我正在寻找一种简化新数据框中输出的简单方法。
df
MessageID NewMessageID
0 28 10
1 21 9
2 4 18
3 3 6
4 18 22
5 99 102
6 102 118
7 1 20
我正在寻找一个输出:
df1
Start Finish
0 28 10
1 21 9
2 4 22
3 3 6
4 99 118
5 1 20
加入自己,创建df2
,从原始df
删除行,这些行在两列之间具有共同的值。 保留df2
的外部两列并重命名它们以匹配df
并将一个附加到另一列。
df = pd.DataFrame({'MessageID':[28,21,4,3,18,99,102,1],'NewMessageID':[10,9,18,6,22,102,118,20]})
df2 = df.merge(df, left_on='NewMessageID', right_on='MessageID')
df2 = df2[['MessageID_x','NewMessageID_y']]
df2.columns = ['MessageID', 'NewMessageID']
df = df[(~df['MessageID'].isin(df['NewMessageID'].values.tolist())) & (~df['NewMessageID'].isin(df['MessageID'].values.tolist()))]
output = df.append(df2)
MessageID NewMessageID
0 28 10
1 21 9
3 3 6
7 1 20
0 4 22
1 99 118
我还有另一种解决方案,因为我注意到最多投票的解决方案不适用于要链接的行数超过两行的情况。 我添加了另一个连接,从22 - > 23,表明它在这种情况下工作。
def main():
b = pd.DataFrame()
b['MessageID'] = [28, 21, 4, 3, 18, 99, 22, 102, 1]
b['NewMessageID'] = [10, 9, 18, 6, 22, 102, 23, 118, 20]
b = b.rename(columns={'MessageID': 'Start', 'NewMessageID': 'End'})
rows_to_drop = []
for i, row in b.iterrows():
recursion(i, row, b, rows_to_drop)
b.drop(index=rows_to_drop, inplace=True)
def recursion(i, row, b, rows_to_drop):
exists = b[b['Start'] == row['End']]
if not exists.empty and i not in rows_to_drop and exists.index[0] not in rows_to_drop:
b.at[i, 'End'] = exists['End']
rows_to_drop.append(exists.index[0])
for _i, _row in b.iterrows():
recursion(_i, _row, b, rows_to_drop)
输出:
Start End
0 28 10
1 21 9
2 4 23
3 3 6
5 99 118
8 1 20
它显然不是最理想的 - 我们在这里迭代数据帧。 但它应该做到这一点,并且对于相对较小的数据集足够有效。
它还有另一个好处 - 我们维持输入订单。
您可以使用名为networkx
的库来解决此networkx
G = (nx.from_pandas_edgelist(
df, source='MessageID', target='NewMessageID', create_using=nx.DiGraph()))
tc = nx.algorithms.dag.transitive_closure(G)
a = df['MessageID'].to_numpy()
b = df['NewMessageID'].to_numpy()
d = pd.DataFrame(tc.edges)
d[~d[1].isin(a) & ~d[0].isin(b)]
0 1
0 28 10
1 21 9
3 4 22
5 3 6
7 99 118
9 1 20
我可能是最好的解决方案(也许是最好的解决方案,因为你不必合并或加入任何东西),虽然它花了我一段时间。 尝试:
Me_in_New = np.where(np.in1d(df['MessageID'], df['NewMessageID']) == True)[0]
New = df['NewMessageID'][Me_in_New]
old_location = np.where(np.in1d(df['NewMessageID'], df['MessageID']) == True)[0]
df['NewMessageID'][old_location] = New.values
df = df.drop(Me_in_New)
df.reset_index(drop = True)
如果有效,请告诉我!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.