我有一个DataFrame,其中包含一些列,例如'n'列和一些行,例如'm'行。我想根据一个column(Column:'x')值对DataFrame行进行分组,而不是完全匹配column'x'值。我需要对附近的值进行分组。例如我的DataFrame是这样的:
y yh x xw w Nxt
0 2987 3129 347 2092 1735.0 501
1 2715 2847 501 1725 1224.0 492
2 2419 2716 490 2196 1704.0 492
3 2310 2373 492 794 302.0 886
4 2309 2370 886 1012 126.0 492
5 2198 2261 497 791 299.0 886
6 2197 2258 886 1010 124.0 492
7 1663 2180 375 1092 600.0 1323
在上面的数据帧中,列“ x”值之间的差在20之间,那么我需要将它们分组到一个新的数据帧中,其余的可以避免。这里的index = 1,2,3,5行可以是一个组,而index = 4,6可以是另一组,因为这些行“ x”列之间的差是20。我的预期输出应该是三个数据帧-{ {1}}:一个保存所有分组的行,df1
:保存另一组行,“ df3”:其余的行,如下所示:
df1:
df2
df2:
y yh x xw w Nxt
1 2715 2847 501 1725 1224.0 492
2 2419 2716 490 2196 1704.0 492
3 2310 2373 492 794 302.0 886
5 2198 2261 497 791 299.0 886
df3:
y yh x xw w Nxt
4 2309 2370 886 1012 126.0 492
6 2197 2258 886 1010 124.0 492
我尝试了Groupby-apply和groupby-transform,但未能成功。如果有人能帮助我获得预期的帮助,那将是极大的帮助。
答案 0 :(得分:0)
根据我的理解,我已经完成了该问题的实现。
group = df.groupby("x").groups
def neighbour(temp):
temp_final = []
final = []
for i in range(len(temp)):
t = []
for j in range(len(temp)):
if abs(temp[i] - temp[j]) <= 20:
t.append(temp[j])
else:
pass
t = sorted(t)
temp_final.append(t)
temp_final = list(set(frozenset(sublist) for sublist in final))
for i in range(len(temp_final)):
u = []
for item in temp_final[i]:
u.append(item)
final.append(u)
return final
dataframes = {}
for i in range(len(val)):
key_name = "dataframe_"+str(i)
dg = pd.DataFrame()
for item in val[i]:
index = list(group[item])
for i in range(len(index)):
dg = dg.append(df.iloc[index[i]])
dataframes[key_name] = dg
如有任何误解,请通知我。
dataframes
{'dataframe_0': Nxt w x xw y yh
5 886.0 299.0 497.0 791.0 2198.0 2261.0
2 492.0 1704.0 490.0 2196.0 2419.0 2716.0
3 886.0 302.0 492.0 794.0 2310.0 2373.0
1 492.0 1224.0 501.0 1725.0 2715.0 2847.0, 'dataframe_1': Nxt
w x xw y yh
0 501.0 1735.0 357.0 2092.0 2987.0 3129.0
7 1323.0 600.0 375.0 1092.0 1663.0 2180.0, 'dataframe_2': Nxt
w x xw y yh
4 492.0 126.0 886.0 1012.0 2309.0 2370.0
6 492.0 124.0 886.0 1010.0 2197.0 2258.0}
这是输出。
答案 1 :(得分:0)
为了将“ x”列中的值分组为20以内,您可以使用shift
并创建一个名为“ group”的列来定位两行之间的所有空格均大于20的位置,值按“ x”排序后。
df = df.sort_values('x')
df.loc[(df.x.shift() < df.x - 20),'group'] = 1 # everytime the jump betweeen two row is more than 20
# use cumsum, ffill and fillna to complete the column group and have a different number for each one
df['group'] = df['group'].cumsum().ffill().fillna(0)
#if the order of indexes matters, you can here add df = df.sort_index() and the code after is the same
输入以下内容,您将得到:
y yh x xw w Nxt group
0 2987 3129 347 2092 1735.0 501 0.0
7 1663 2180 375 1092 600.0 1323 1.0
2 2419 2716 490 2196 1704.0 492 2.0
3 2310 2373 492 794 302.0 886 2.0
5 2198 2261 497 791 299.0 886 2.0
1 2715 2847 501 1725 1224.0 492 2.0
4 2309 2370 886 1012 126.0 492 3.0
6 2197 2258 886 1010 124.0 492 3.0
现在,当组中有多行时,您可以为每个组创建一个数据框列表。您需要在'x'上使用groupby
,filter
长度大于1的组。最后,将所有长度为1的组添加为一个数据帧:
list_df = [df_g for name_g, df_g in df.groupby('group').filter(lambda x: len(x)>1).groupby('group')] +\
[df.groupby('group').filter(lambda x: len(x)==1)]
,例如,您最终将列表的每个元素作为所需的数据框之一。
print (list_df [0])
y yh x xw w Nxt group
2 2419 2716 490 2196 1704.0 492 2.0
3 2310 2373 492 794 302.0 886 2.0
5 2198 2261 497 791 299.0 886 2.0
1 2715 2847 501 1725 1224.0 492 2.0
或
print (list_df [-1])
y yh x xw w Nxt group
0 2987 3129 347 2092 1735.0 501 0.0
7 1663 2180 375 1092 600.0 1323 1.0
我看到您想要为每个人取一个名字,但是我认为如果它们在列表中,访问起来会更容易