首页 > 解决方案 > 如何在 Python 中向 DF 添加/估算附加行

问题描述

我有一个看起来像这样的数据框:

ID 分数 年龄 性别 日期
一种 25 5 2019-01-01
一种 32 5 2019-01-01
一种 32 5 2019-01-05
45 9 F 2019-02-01
76 9 F 2019-05-01
C 54 7 F 2019-03-01

对于每个唯一 ID,我想确保恰好有 2 个条目。如果一个 ID 有超过 2 个条目,我想要两个具有最新日期的条目(如果出现平局,只需使用日期的任意两行)。如果一个 ID 的条目少于 2 个,则为该 ID 插入/估算一行,其中分数设置为 0,日期设置为该 ID 的最近日期,但保留年龄和性别(假设年龄和任何一个 ID 的性别总是相同的)。

一种可能的解决方案是:

ID 分数 年龄 性别 日期
一种 32 5 2019-01-01
一种 32 5 2019-01-05
45 9 F 2019-02-01
76 9 F 2019-05-01
C 54 7 F 2019-03-01
C 0 7 F 2019-03-01

我的数据集非常大,因此使用 pd.multiIndex 进行多重索引使我的内存很快耗尽(我使用的实际数据集大约有 50 万行)。

我尝试实现类似于这里的东西: How to pad on extra rows in dataframe for Neural Netowrk

但我不确定如何实施“使用最新日期”限制。

标签: pythonpandas

解决方案


蛮力

def f(d):
    d = d.nlargest(2, ['Date'])
    if len(d) < 2:
        d = d.append(d.assign(Score=0))
    return d

df.groupby('ID', as_index=False, group_keys=False).apply(f)

# ⇓ Ugly index is ugly

    ID  Score  Age Gender       Date
  2  A     32    5      M 2019-01-05
  0  A     25    5      M 2019-01-01
  4  B     76    9      F 2019-05-01
  3  B     45    9      F 2019-02-01
  5  C     54    7      F 2019-03-01
  5  C      0    7      F 2019-03-01

如果您想要除 以外的特定数字2,请说5

def f(d, limit):
    d = d.nlargest(limit, ['Date'])
    if len(d) < limit:
        d = pd.concat([d] + [d.assign(Score=0)] * (limit - len(d)))
    return d

df.groupby('ID', as_index=False, group_keys=False).apply(f, limit=5)

少一点蛮力,也许?

pd.concat([
    d.append(d.assign(Score=0)) if len(d) < 2 else d.tail(2)
    for _, d in df.sort_values(['ID', 'Date']).groupby('ID')
], ignore_index=True)

  ID  Score  Age Gender       Date
0  A     32    5      M 2019-01-01
1  A     32    5      M 2019-01-05
2  B     45    9      F 2019-02-01
3  B     76    9      F 2019-05-01
4  C     54    7      F 2019-03-01
5  C      0    7      F 2019-03-01

推荐阅读