首页 > 解决方案 > 如何检查前几个月列表中是否存在标识符

问题描述

我试图确定一个标识符是否在给定月份首先出现(即它是标识符列表中的“新”)。下面是第一次尝试,但它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(

在此处输入图像描述

标签: pythonpandasdataframepandas-groupby

解决方案


使用pd.to_datetimedate列转换为熊猫datetime系列:

df['date'] = pd.to_datetime(df['date'])

然后使用:

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)

细节:

使用DataFrame.groupbyon和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

Series.unstack在序列s1上使用reshape它,然后用于DataFrame.diff计算标识符计数之间的连续差异,这一步将有助于识别repeated标识符的出现previous month,接下来使用DataFrame.stack它再次将其转换为MultiLevel名为的索引序列s2

# 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

用于set_index将数据帧的索引设置dfdateidentifier并用于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

推荐阅读