繁体   English   中英

Pandas即使在不同的行上,如何创建具有开始和结束的新数据帧

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM