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)
使用将列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将数据帧的索引设置df为dateandidentifier并用于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)