熊猫-创建新列,其中值取自同一数据框中的其他行

时间:2020-01-06 09:24:55

标签: python pandas dataframe

我有这样的DataFrame

    message_id  reply_to_id     sender
0   1           0               Roozbeh
1   2           1               Amir
2   3           0               Neda
3   4           2               Roozbeh
3   5           2               Neda

如果该消息是对另一条消息的答复,则reply_to_id会显示已回复的消息的ID,否则为0。现在,我想创建另一列reply_to_sender,在其中显示已回复邮件的发件人的名称(如果不是答复,则可以显示NaN)< / p>

message_id列是唯一的,但是reply_to_idsender列显然不是。

我尝试过:

data["reply_to_sender"] = data.loc[data["reply_to_id"] == data["message_id"]]["sender"]

但是它显然行不通,因为它会查看每一行并执行关系操作。我想做的是查看每一行,然后从其他行中找到发件人的名字。对于上面的示例,输出需要像这样:

    message_id  reply_to_id     sender    reply_to_sender
0   1           0               Roozbeh   NaN
1   2           1               Amir      Roozbeh
2   3           0               Neda      NaN
3   4           2               Roozbeh   Amir
3   5           2               Neda      Amir

我该怎么做?

3 个答案:

答案 0 :(得分:5)

Series.mapSeriesmessage_id创建的sender一起使用:

df['reply_to_sender'] = df['reply_to_id'].map(df.set_index('message_id')['sender'])
print (df)
   message_id  reply_to_id   sender reply_to_sender
0           1            0  Roozbeh             NaN
1           2            1     Amir         Roozbeh
2           3            0     Neda             NaN
3           4            2  Roozbeh            Amir
3           5            2     Neda            Amir

答案 1 :(得分:0)

首先,让我们看看您将如何手动完成此操作。然后我们用代码实现它。

如果我给您一个reply_to_id,只需查看DataFrame,找到message_id等于该行的行,就可以告诉我此消息是谁的回复数字,然后告诉我该行的sender列中的值。可以这样完成,其中reply_to_id变量是我给您的数字:

data.loc[data["message_id"] == reply_to_id]["sender"]

现在此代码返回一个pandas.Series,但我们没有要求一个Series,而是要求了一个标量值,它是发送者的名字。因此,我们需要从系列中提取该值。如果系列中只有一个值(您需要检查),我们可以使用pandas.Series.values[0]提取它。所以代码变成这样:

reply_to_sender_values = data.loc[data["message_id"] == reply_to_id]["sender"].values
if len(reply_to_sender_values) == 1:
    return reply_to_sender_values[0]

现在,如果我给您一个您在message_id中找不到的电话号码会怎样?你会怎么做?您会告诉我您什么都没找到。就是这样:

reply_to_sender_values = data.loc[data["message_id"] == reply_to_id]["sender"].values
if len(reply_to_sender_values) == 1:
    return reply_to_sender_values[0]
else:
    return ""

我们还需要注意一件事。如您所说,reply_to_id中的值可以为零。因此,我们需要注意以下事项:

if(reply_to_id != 0):
    reply_to_sender_values = data.loc[data["message_id"] == reply_to_id]["sender"].values
    if len(reply_to_sender_values) == 1:
        return reply_to_sender_values[0]
    else:
        return ""
else:
    return ""

如您所见,我们刚刚构建了一个函数来手动执行操作。我们给它起个名字:

def reply_to_sender(reply_to_id):
    if(reply_to_id != 0):
        reply_to_sender_values = data.loc[data["message_id"] == reply_to_id]["sender"].values
        if len(reply_to_sender_values) == 1:
            return reply_to_sender_values[0]
        else:
            return ""
    else:
        return ""

剩下要做的就是找到一种方法,在我们reply_to_id的{​​{1}}列的所有行上应用。幸运的是,DataFrame中有一个方法可以做到这一点。您猜对了,它叫做pandas.DataFrame.apply。现在,所有这些都与以下代码行一起出现:

Pandas

值得注意的是,我在 Jupyter Notebook中测试了此代码。如果要从脚本运行此代码,则需要将data["reply_to_sender"] = data["reply_to_id"].apply(lambda x: reply_to_sender(x)) 传递给{{1 }}函数。因此代码更改为:

DataFrame

答案 2 :(得分:0)

你可以做

mymap = {val: df.sender.loc[key] for key, val in df.message_id.to_dict().items()}

然后

df['reply_to_sender'] = df.reply_to_id.map(mymap)

这给你

   message_id  reply_to_id   sender reply_to_sender
0           1            0  Roozbeh             NaN
1           2            1     Amir         Roozbeh
2           3            0     Neda             NaN
3           4            2  Roozbeh            Amir
3           5            2     Neda            Amir