【问题标题】:Group nearby column values in Python Dataframe在 Python Dataframe 中对附近的列值进行分组
【发布时间】:2019-01-03 08:40:42
【问题描述】:

我有一个 DataFrame,其中包含一些列,例如“n”列和一些行,例如“m”行。我想根据一列(列:'x')值对 DataFrame 行进行分组,它与列'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 之间。我的预期输出应该是三个数据帧-@ 987654322@:one 持有所有分组的行,df2:持有另一组行和 'df3': 其余行如下:

df1:

      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

df2:

      y    yh     x    xw       w   Nxt
4   2309  2370   886  1012   126.0   492
6   2197  2258   886  1010   124.0   492

df3:

    y    yh     x    xw       w   Nxt
0   2987  3129   347  2092  1735.0   501
7   1663  2180   375  1092   600.0  1323

我尝试使用 Groupby-apply 和 groupby-transform,但未能成功。如果有人能帮助我得到这个预期的,那将是很大的帮助,在此先感谢。

【问题讨论】:

  • 第4行和第7行的差值也小于20,这些行也要单独分组吗?
  • 第 0 行和第 7 行的 x 列的值彼此相差 20 以内,所以它们应该在另一个数据框中吗?第 4 行和第 6 行一样吗?我的问题是真的,你是怎么决定df1 只包含 x 值在 500 左右的组?
  • @user2699,是的,这些行也可以单独分组为另一个数据框,如 df3...
  • 你怎么知道它们可以组合在一起的范围?
  • @Ben.T,是的,对于第 4 行和第 6 行,它应该是另一个数据框 df3... 对于第 0 行和第 7 行,我已经编辑了值,这是类型错误,抱歉。

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


【解决方案1】:

根据我的理解,我已经完成了问题的实现。

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}

这是输出。

【讨论】:

  • 感谢您的解决方案和努力....但我更感兴趣的是通过内置函数而不是传统的循环方式来获得它....
【解决方案2】:

为了将 '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

我知道你想为每个人命名,但我认为如果它们在列表中会更容易访问它们

【讨论】:

  • 太棒了...这就是我所期望的。非常感谢您理解我的问题并帮助提供正确的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-20
相关资源
最近更新 更多