使用pandas操作创建派生列

时间:2019-06-21 11:10:27

标签: python pandas dataframe

我正在尝试创建一列,其中包含项tid的累积总和,这些项根据(raceid, tid)的唯一值进行分组。累积总和应按下面df3 dataframe所示的分组中的条目数递增,而不是一次递增。

import pandas as pd

df1 = pd.DataFrame({
    'rid': [1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 5, 5],
    'tid': [1, 2, 2, 1, 1, 3, 1, 4, 5, 1, 1, 1, 3]})

    rid  tid
0     1    1
1     1    2
2     1    2
3     2    1
4     2    1
5     2    3
6     3    1
7     3    4
8     4    5
9     5    1
10    5    1
11    5    1
12    5    3

进行所需操作后提供:

df3 = pd.DataFrame({
    'rid': [1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 5, 5],
    'tid': [1, 2, 2, 1, 1, 3, 1, 4, 5, 1, 1, 1, 3],
    'groupentries': [1, 2, 2, 2, 2, 1, 1, 1, 1, 3, 3, 3, 1],
    'cumulativeentries': [1, 2, 2, 3, 3, 1, 4, 1, 1, 7, 7, 7, 2]})

    rid  tid  groupentries  cumulativeentries
0     1    1             1                  1
1     1    2             2                  2
2     1    2             2                  2
3     2    1             2                  3
4     2    1             2                  3
5     2    3             1                  1
6     3    1             1                  4
7     3    4             1                  1
8     4    5             1                  1
9     5    1             3                  7
10    5    1             3                  7
11    5    1             3                  7
12    5    3             1                  2

尽管我只想出了如何使用cumulativeentries来生成中间列groupentries,但我追随的派生列是pandas列:

df1.groupby(["rid", "tid"]).size()

2 个答案:

答案 0 :(得分:0)

对于第一列,将GroupBy.transformDataFrameGroupBy.size一起使用,对于第二次使用自定义函数,以测试列到最后索引值的所有值,与最后一个值进行比较,并通过sum对匹配值进行计数:

f = lambda x:  (df1['tid'].iloc[:x.index[-1]+1] == x.iat[-1]).sum()
df1['groupentries'] = df1.groupby(["rid", "tid"])['rid'].transform('size')
df1['cumulativeentries']  = df1.groupby(["rid", "tid"])['tid'].transform(f)
print (df1)
    rid  tid  groupentries  cumulativeentries
0     1    1             1                  1
1     1    2             2                  2
2     1    2             2                  2
3     2    1             2                  3
4     2    1             2                  3
5     2    3             1                  1
6     3    1             1                  4
7     3    4             1                  1
8     4    5             1                  1
9     5    1             3                  7
10    5    1             3                  7
11    5    1             3                  7
12    5    3             1                  2

答案 1 :(得分:0)

getLastError()中的值实际上是一种运行计数。 任务是计算当前 tid 在“来源区域”中的出现次数 tid 列:

  • 从DataFrame的开头开始,
  • 直到(包括)当前组的末尾。

为了计算每个组的两个必需值的值,我定义了 以下功能:

cumulativeentries

要获取上述“源区域”,我使用了 truncate 函数。 我认为,这是一个非常直观的解决方案,基于 “源区域”。

该函数返回包含两个必需值的列表:

  • 当前组的大小
  • 与当前 tid 相等的 tid 个 截短的 tid 列。

要应用此功能,请运行:

def fn(grp):
    lastRow = grp.iloc[-1]  # last row of the current group
    lastId = lastRow.name   # index of this row
    tids = df1.truncate(after=lastId).tid
    return [grp.index.size, tids[tids == lastRow.tid].size]

详细信息:

  • apply(fn)生成一个包含2个元素列表的 Series
  • apply(pd.Series)将其转换为DataFrame(具有默认列名)。
  • 重命名设置目标列名称。

最后要做的就是将此表连接到 df1

df2 = df1.groupby(['rid', 'tid']).apply(fn).apply(pd.Series)\
    .rename(columns={0: 'groupentries', 1: 'cumulativeentries'})