可复制的示例:
df = pd.DataFrame([[1, '2015-12-15', 10],
[1, '2015-12-16', 13],
[1, '2015-12-17', 16],
[2, '2015-12-15', 19],
[2, '2015-12-11', 22],
[2, '2015-12-18', 25],
[3, '2015-12-14', 28],
[3, '2015-12-12', 31],
[3, '2015-12-15', 34]])
df.columns = ['X', 'Y', 'Z']
print(df.dtypes)
print()
print(df)
可重现示例的输出和每一列的数据类型:
X int64
Y object
Z int64
dtype: object
X Y Z
0 1 2015-12-15 10
1 1 2015-12-16 13
2 1 2015-12-17 16
3 2 2015-12-15 19
4 2 2015-12-11 22
5 2 2015-12-18 25
6 3 2015-12-14 28
7 3 2015-12-12 31
8 3 2015-12-15 34
预期输出:
X Y Z
0 1 2015-12-15 10
1 1 2015-12-15 10
2 2 2015-12-11 22
3 2 2015-12-15 19
4 3 2015-12-12 31
5 3 2015-12-15 34
说明该输出是什么
对于按X
分组后的X
列中的每个组,我想要一行包含Z
列中的值的行
其中该组的Y
列中的值是min(all dates/object in column Y)
且相同
组中,在“ Z”列中具有值的另一行,其中该组的Y
列中的值为some custom date that definitely exists for all groups which will be hardcoded
。因此,每个组将有两行。
在我的输出中,对于组1
,列Z
中的值是10
,因为列Z
中的值与
Y
组1
中12-15-2015
列中所有日期的最小值。对于同一组10
,该组1
的第二行,自定义日期1
的列Z
中的值也是12-15-2015
。对于组10
,2
是min(all dates/objects in column Y)
,组2015-12-11
在列Z
中的对应值在列2
,{{1中}}是Y
。对于自定义日期2015-12-11
,则为22
。
这就是我为实现此目的而编写的一些线性时间搜索/延迟代码:
12-15-2015
我的印象是有一种巧妙的方法,您只需执行19
并获得预期的输出,我希望有人可以向我提供此代码。
答案 0 :(得分:2)
IIUC
g1=df.groupby('X').Y.value_counts().count(level=1).eq(df.X.nunique()) # get group1 , all date should show in three groups , we using value_counts
df.Y=pd.to_datetime(df.Y) # change to date format in order to sort
g2=df.sort_values('Y').groupby('X').head(1) # get the min date row .
pd.concat([df.loc[df.Y.isin(g1[g1].index)],g2]).sort_index() # combine all together
Out[280]:
X Y Z
0 1 2015-12-15 10
0 1 2015-12-15 10
3 2 2015-12-15 19
4 2 2015-12-11 22
7 3 2015-12-12 31
8 3 2015-12-15 34
答案 1 :(得分:1)
使用-
date_fill = dt.datetime.strptime('2015-12-15', '%Y-%m-%d')
df['Y'] = pd.to_datetime(df['Y'], format='%Y-%m-%d')
df_g = df.loc[df.groupby(['X'])['Y'].idxmin()]
df2 = df[df['Y']==date_fill]
target_map = pd.Series(df2['Z'].tolist(),index=df2['X']).to_dict()
df_g.index = range(1, 2*len(df_g)+1, 2)
df_g = df_g.reindex(index=range(2*len(df_g)))
df_g['Y'] = df_g['Y'].fillna(date_fill)
df_g = df_g.bfill()
df_g.loc[df_g['Y']==date_fill, 'Z'] = df_g[df_g['Y']==date_fill]['X'].map(target_map)
df_g = df_g.bfill()
print(df_g)
输出
X Y Z
0 1.0 2015-12-15 10.0
1 1.0 2015-12-15 10.0
2 2.0 2015-12-15 19.0
3 2.0 2015-12-11 22.0
4 3.0 2015-12-15 34.0
5 3.0 2015-12-12 31.0
说明
date_fill
df.groupby(['X'])['Y'].idxmin()
提取min
的{{1}}的行Y
是为了在以后保留target_map
值而创建的字典Z
扩展为每隔一列具有df_g
个值na
中输入一个df_g = df_g.bfill()
中不存在的日期,则date_fill
会出现两次。在这种情况下,df
将不会填充,您最终将获得target_map
值。我确信可以在某种程度上进行优化,但是思考过程应该可以帮助您继续进行。