Pandas/Pythonic方式到groupby列X,在每个组中,根据列Z中的值返回列Y中的值
可复制示例:Pandas/Pythonic方式到groupby列X,在每个组中,根据列Z中的值返回列Y中的值,python,python-3.x,pandas,pandas-groupby,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-1
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(Y列中的所有日期/对象)
和相同的值
组,另一行的值在“Z”列中,其中该组的Y列中的值是所有将被硬编码的组肯定存在的某个自定义日期。所以每个小组有两行
在我的输出中,对于组1
,列Z
中的值是10
,因为列Z
中的值与
组1
,12-15-2015
的Y列中所有日期的最小值为10
。对于同一组1
,此组的第二行1
,自定义日期12-15-2015
列Z
中的值也是10
。对于组2
,min(Y列中的所有日期/对象)
是2015-12-11
,对于组2
和列Y
中的值,2015-12-11
是22
。而定制日期12-15-2015
,则为19
以下是我为实现这一点而编写的一些线性时间搜索/延迟代码:
uniqueXs = list(dict(Counter(df['X'].tolist())).keys()) #Get every unique item in column X is a list.
df_list = [] #Empty list that will have rows of my final DataFrame
for x in uniqueXs: #Iterate through each unique value in column X
idfiltered_dataframe = df.loc[df['X'] == x] #Filter DataFrame based on the current value in column X
#(iterating through list of all values)
min_date = min(idfiltered_dataframe['Y']) #Min of column Y
custom_date = '2015-12-15' #Every group WILL have this custom date.
mindatefiltered_dataframe = idfiltered_dataframe.loc[idfiltered_dataframe['Y'] == min_date] #Within group, filter rows where column Y has minimum date
customdatefiltered_dataframe = idfiltered_dataframe.loc[idfiltered_dataframe['Y'] == custom_date] #Within group, filter rows where column Y has a custom date
for row_1 in mindatefiltered_dataframe.index: #Iterate through mindatefiltered DataFrame and create list of each row value required
row_list = [mindatefiltered_dataframe.at[row_1, 'X'], mindatefiltered_dataframe.at[row_1, 'Y'], mindatefiltered_dataframe.at[row_1, 'Z']]
df_list.append(row_list) #Append to a master list
for row_2 in customdatefiltered_dataframe.index: #Iterate through customdatefiltered DataFrame and create list of each row value required
row_list = [customdatefiltered_dataframe.at[row_2, 'X'], customdatefiltered_dataframe.at[row_2, 'Y'], customdatefiltered_dataframe.at[row_2, 'Z']]
df_list.append(row_list) #Append to a master list
print(pd.DataFrame(df_list)) #Create DataFrame out of the master list
我的印象是,有一种巧妙的方法,你只需做df.groupby..
就可以得到预期的输出,我希望有人能为我提供这样的代码。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
IIUC
使用-
输出
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\u fill
df.groupby(['X'])['Y'].idxmin()
按Y的min
获取行
target\u map
是一个创建的dict,用于在以后保留Z
值
接下来,扩展df_g
,使每个备用列都有na
值
如果在date\u fill
中输入了df
中不存在的日期,则df\u g=df\u g.bfill()
会出现两次。在这种情况下,target\u map
将不会填充,最终将获得na
值
我相信这可以进行一些优化,但思考过程应该有助于您继续。使用-
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\u fill
df.groupby(['X'])['Y'].idxmin()
按Y的min
获取行
target\u map
是一个创建的dict,用于在以后保留Z
值
接下来,扩展df_g
,使每个备用列都有na
值
如果在date\u fill
中输入了df
中不存在的日期,则df\u g=df\u g.bfill()
会出现两次。在这种情况下,target\u map
将不会填充,最终将获得na
值
我相信这可以进行一些优化,但思考过程应该可以帮助您继续。感谢您的努力!在我接受之前,如果不太麻烦的话,我想了解一下你的答案的哪一部分是每组的第二排?因为这只是一个可复制的例子,在我更大的例子中,我必须根据没有任何模式的自定义日期进行过滤!在我的可复制示例中,结果是在我的示例中,对于组1
,2015-12-15
既是mindate
,也是customdate
。感谢您的努力!在我接受之前,如果不太麻烦的话,我想了解一下你的答案的哪一部分是每组的第二排?因为这只是一个可复制的例子,在我更大的例子中,我必须根据没有任何模式的自定义日期进行过滤!在我的可复制示例中,在我的示例中,对于组1
,2015-12-15
既是mindate
,也是customdate
。。