用熊猫/ Pythonic方式对每列中的X列进行分组的方法,基于Z列中的值返回Y列中的值

时间:2018-08-04 01:48:29

标签: python python-3.x pandas pandas-groupby

可复制的示例:

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中的值与 Y112-15-2015列中所有日期的最小值。对于同一组10,该组1的第二行,自定义日期1的列Z中的值也是12-15-2015。对于组102min(all dates/objects in column Y),组2015-12-11在列Z中的对应值在列2,{{1中}}是Y。对于自定义日期2015-12-11,则为22

这就是我为实现此目的而编写的一些线性时间搜索/延迟代码:

12-15-2015

我的印象是有一种巧妙的方法,您只需执行19并获得预期的输出,我希望有人可以向我提供此代码。

2 个答案:

答案 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

说明

  1. 将所需的自定义日期放入date_fill
  2. df.groupby(['X'])['Y'].idxmin()提取min的{​​{1}}的行
  3. Y是为了在以后保留target_map值而创建的字典
  4. 接下来,将Z扩展为每隔一列具有df_g个值
  5. 如果您在na中输入一个df_g = df_g.bfill()中不存在的日期,则
  6. date_fill会出现两次。在这种情况下,df将不会填充,您最终将获得target_map值。

我确信可以在某种程度上进行优化,但是思考过程应该可以帮助您继续进行。