在Python Dataframe中将附近的列值分组

时间:2018-07-26 11:05:18

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

我有一个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,但未能成功。如果有人能帮助我获得预期的帮助,那将是极大的帮助。

2 个答案:

答案 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'上使用groupbyfilter长度大于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

我看到您想要为每个人取一个名字,但是我认为如果它们在列表中,访问起来会更容易