如何引用熊猫数据框中的其他行套用

时间:2020-07-28 19:18:00

标签: python pandas dataframe

我有一个类似于以下内容的数据框:

| Session | Leg | Talk Time Seconds | ... |
| ------- | --- | ----------------- | --- |
| 1       | 1   | 0                 | ... |
| 1       | 2   | 40                | ... |
| 2       | 1   | 35                | ... |
| 2       | 2   | 50                | ... |
| ...     | ... | ...               | ... |

如果它不是特定会话中的最后一条腿,并且通话时间> 0,则应将该腿标记为已转移,因此:

| Session | Leg | Talk Time Seconds | Transfer | ... |
| ------- | --- | ----------------- | -------- | --- |
| 1       | 1   | 0                 | False    | ... |
| 1       | 2   | 40                | False    | ... |
| 2       | 1   | 35                | True     | ... |
| 2       | 2   | 50                | False    | ... |
| ...     | ... | ...               | ...      | ... |

我目前正在通过将数据帧分解为每个会话的数据帧列表来完成此操作。使用 apply ,然后将数据帧串联在一起。这需要很长时间才能运行,我想知道是否有更好的方法可以做到这一点。我的代码如下:

# get list of unique sessions
sessions = df['Session'].unique().tolist()

# list of dataframes for each session
session_dfs = [df[df['Session'] == session] for session in sessions]

# if it is not the last leg of the session and talk time is greater than 1 we can assume it is a transfer
for sdf in session_dfs:
    last_leg = sdf['Leg'].max()
    sdf['Transfer'] = sdf.apply(lambda row: row['Talk Time Seconds'] > 0 if row['Leg'] != last_leg else False, axis=1)

# join all the session dataframes into one dataframe
df = pd.concat(session_dfs)

编辑: 尝试以下建议时:

df['Transfer'] = (
    df
      .groupby("Session", as_index=True)
      .apply(lambda x: (x['Leg'] != x['Leg'].max()) & (x['Talk Time Seconds'].gt(0)))
      .reset_index(drop=True)
)

我得到以下输出:

>>> df[(df['Transfer']==1) & (df['Talk Time Seconds'] == 0)][['Session','Leg','Talk Time Seconds','Transfer']]

        Session         Leg   Talk Time Seconds    Transfer
11060   51000011288     1     0                    True
16167   51000011528     1     0                    True
15176   51000012182     1     0                    True
8468    51000012228     1     0                    True
2175    51000012585     2     0                    True

看起来是在通话时间为0的情况下发生的,但这是通话的最后一站:

>>> df[df['Session'] == 51000012585][['Session','Leg','Talk Time Seconds','Transfer']]

        Session         Leg   Talk Time Seconds    Transfer
2175    51000012585     2     0                    True
3452    51000012585     1     0                    False

3 个答案:

答案 0 :(得分:2)

这是一种方法。

首先,创建数据框:

d = {'Session': {0: 1, 1: 1, 2: 2, 3: 2},
 'Leg': {0: 1, 1: 2, 2: 1, 3: 2},
 'TalkTimeSeconds': {0: 0, 1: 40, 2: 35, 3: 50}}
df = pd.DataFrame.from_dict(d)

第二,找到每个会话的最大航段号; .groupby().transform()返回的序列与原始序列的长度相同。

df['max_leg'] = df.groupby('Session')['Leg'].transform('max')

第三,应用逻辑来识别传输(在最后一站之前,时间> 0):

df['Transfer'] = (df['Leg'] < df['max_leg']) & (df['TalkTimeSeconds'] > 0)

结果显示在下面(我留在max_leg中),以显示groupby / transform语句的结果):

   Session  Leg  TalkTimeSeconds  max_leg  Transfer
0        1    1                0        2     False
1        1    2               40        2     False
2        2    1               35        2      True
3        2    2               50        2     False

答案 1 :(得分:1)

我建议使用掩码来识别这是否是当前Leg中的最后一个Session,以及另一个是否匹配Talk Time Seconds上的条件。

对于第一部分,您可以group by获取每个Leg中最大的Session,然后使用pd.Series.map检查条件。对于第二个过去,简单的过滤器就足够了。

以下代码应满足您的要求

df["Transfer"] = (df["Leg"] != df["Session"].map(df.groupby("Session")["Leg"].max())) & (df["Talk Time Seconds"] > 0)

答案 2 :(得分:0)

您可以这样做:

a.index - b.index