如何检查前几个月列表中是否存在标识符

Kai*_*rli 5 python dataframe pandas pandas-groupby

我试图确定标识符是否在给定月份中首先出现(即它对于标识符列表来说是“新的”)。下面是第一次尝试,但它将标识符标记a3为 2020 年 2 月 28 日旧的标识符,尽管它不在 2020 年 1 月 31 日的列表中。

请注意,这是一个简化的示例:实际上,我会有更多的按列分组,而不仅仅是日期,并且我需要检查标识符对于由日期、行业、年龄组合创建的“单元格”是否是新的等等。可能有很多。

import pandas as pd, numpy as np

data = """
date                            identifier     value
 31-Dec-2019                    a1   10
 31-Dec-2019                    a2   20
 31-Dec-2019                    a3   30
 31-Jan-2020                    a1   40
 31-Jan-2020                    a2   50
 31-Jan-2020                    a4   60
 31-Jan-2020                    a5   60
 28-Feb-2020                    a1   70
 28-Feb-2020                    a4   80
 28-Feb-2020                    a3   90
"""

res=[]
for row in [el.split() for el in data.splitlines()][1:]:
    rrow=[]
    for col in row:
        try:
            if float(col):
                col = np.float32(col)
        except:
            pass
        rrow.append(col)
    res.append(rrow)
df = pd.DataFrame(data=res[1:], columns=res[0])

df.date = pd.to_datetime(df.date)
df = df.set_index(["date", "identifier"]).sort_index()

df["valprev"] = df.groupby(level="identifier")["value"].shift(1)
df["isnew"] = df.valprev.isnull(
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Shu*_*rma 1

使用将列pd.to_datetime转换date为 pandasdatetime系列:

df['date'] = pd.to_datetime(df['date'])
Run Code Online (Sandbox Code Playgroud)

然后使用:

s1 = df.groupby('date')['identifier'].value_counts()
s2 = s1.unstack().diff().replace({0: False, np.nan: True}).stack()
df['isnew'] = df.set_index(['date', 'identifier']).index.map(s2)
Run Code Online (Sandbox Code Playgroud)

细节:

使用DataFrame.groupby以下方法聚合date列:identifierGroupby.value_counts

# print(s1):

date        identifier
2019-12-31  a1            1
            a2            1
            a3            1
2020-01-31  a1            1
            a2            1
            a4            1
            a5            1
2020-02-28  a1            1
            a3            1
            a4            1
Name: identifier, dtype: int64
Run Code Online (Sandbox Code Playgroud)

对它使用Series.unstackon 系列,然后使用计算标识符计数之间的连续差异,此步骤将有助于识别 中标识符的出现,下一步使用将其再次转换为名为 的索引系列。s1reshapeDataFrame.diffrepeatedprevious monthDataFrame.stackMultiLevels2

# s1.unstack().diff()
identifier   a1   a2  a3   a4  a5
date                             
2019-12-31  NaN  NaN NaN  NaN NaN
2020-01-31  0.0  0.0 NaN  NaN NaN
2020-02-28  0.0  NaN NaN  0.0 NaN

# print(s2) # this series will be use to map in next step
date        identifier
2019-12-31  a1             True
            a2             True
            a3             True
            a4             True
            a5             True
2020-01-31  a1            False
            a2            False
            a3             True
            a4             True
            a5             True
2020-02-28  a1            False
            a2             True
            a3             True
            a4            False
            a5             True
dtype: bool
Run Code Online (Sandbox Code Playgroud)

用于set_index将数据帧的索引设置dfdateandidentifier并用于Series.map从值映射此索引s2,将此映射值分配给新列isnew

# print(df)
        date identifier  value  isnew
0 2019-12-31         a1     10   True
1 2019-12-31         a2     20   True
2 2019-12-31         a3     30   True
3 2020-01-31         a1     40  False
4 2020-01-31         a2     50  False
5 2020-01-31         a4     60   True
6 2020-01-31         a5     60   True
7 2020-02-28         a1     70  False
8 2020-02-28         a4     80  False
9 2020-02-28         a3     90   True
Run Code Online (Sandbox Code Playgroud)