【问题标题】:Pandas iterate over DataFrame row pairsPandas 遍历 DataFrame 行对
【发布时间】:2018-12-28 20:03:25
【问题描述】:

如何迭代 Pandas DataFrame 的成对行?

例如:

content = [(1,2,[1,3]),(3,4,[2,4]),(5,6,[6,9]),(7,8,[9,10])]
df = pd.DataFrame( content, columns=["a","b","interval"])
print df

输出:

   a  b interval
0  1  2   [1, 3]
1  3  4   [2, 4]
2  5  6   [6, 9]
3  7  8  [9, 10]

现在我想做类似的事情

for (indx1,row1), (indx2,row2) in df.?
    print "row1:\n", row1
    print "row2:\n", row2
    print "\n"

应该输出哪个

row1:
a    1
b    2
interval    [1,3]
Name: 0, dtype: int64
row2:
a    3
b    4
interval    [2,4]
Name: 1, dtype: int64

row1:
a    3
b    4
interval    [2,4]
Name: 1, dtype: int64
row2:
a    5
b    6
interval    [6,9]
Name: 2, dtype: int64

row1:
a    5
b    6
interval    [6,9]
Name: 2, dtype: int64
row2:
a    7
b    8
interval    [9,10]
Name: 3, dtype: int64

有没有内置的方法来实现这一点? 我查看了 df.groupby(df.index // 2) 和 df.itertuples 但这些方法似乎都没有达到我想要的效果。

编辑: 总体目标是获取一个布尔列表,指示“间隔”列中的间隔是否重叠。在上面的示例中,列表将是

overlaps = [True, False, False]

所以每对都有一个布尔值。

【问题讨论】:

  • 你可以试试 shift,它本质上会返回一个“下一行”的数据框。
  • 如何将 df 和 df.shift(1) 结合起来?
  • 为什么要循环播放?发布您更大的问题..您可能不需要循环
  • 数据框的一列在每一行中都包含一个区间,我想检查区间是否成对重叠。
  • @Lxndr 实际上,您的问题已被多次询问(间隔问题)。绝对不需要循环来执行此操作。随着数据框大小的增加,速度会变得非常慢

标签: python pandas loops dataframe


【解决方案1】:

使用axis=1 移动数据帧并将其连接回原始数据帧,以便每个间隔和下一个间隔在同一行中

df_merged = pd.concat([df, df.shift(-1).add_prefix('next_')], axis=1)
df_merged
#Out:
   a  b interval     next_a     next_b    next_interval
0  1  2   [1, 3]        3.0        4.0           [2, 4]
1  3  4   [2, 4]        5.0        6.0           [6, 9]
2  5  6   [6, 9]        7.0        8.0          [9, 10]
3  7  8  [9, 10]        NaN        NaN              NaN

定义一个与您的列表表示一起使用的相交函数并应用于合并的数据框,忽略 shifted_interval 为空的最后一行

def intersects(left, right):
    return left[1] > right[0]

df_merged[:-1].apply(lambda x: intersects(x.interval, x.next_interval), axis=1)
#Out:
0     True
1    False
2    False
dtype: bool

【讨论】:

  • 这太棒了!我会将@Ben.T 的答案保留为已接受,因为它更好地回答了我原来的问题。不过,我会用它来解决我的问题!
【解决方案2】:

如果您想保持循环for,使用zipiterrows 可能是一种方法

for (indx1,row1),(indx2,row2) in zip(df[:-1].iterrows(),df[1:].iterrows()):
    print "row1:\n", row1
    print "row2:\n", row2
    print "\n"

要同时访问下一行,请在第二行之后使用df[1:].iterrows() 开始第二个迭代。并以您想要的方式获得输出。

row1:
a    1
b    2
Name: 0, dtype: int64
row2:
a    3
b    4
Name: 1, dtype: int64


row1:
a    3
b    4
Name: 1, dtype: int64
row2:
a    5
b    6
Name: 2, dtype: int64


row1:
a    5
b    6
Name: 2, dtype: int64
row2:
a    7
b    8
Name: 3, dtype: int64

但正如@RafaelC 所说,执行for 循环可能不是解决一般问题的最佳方法。

【讨论】:

    【解决方案3】:

    要获得您显示的输出,请使用:

    for row in df.index[:-1]:
        print 'row 1:'
        print df.iloc[row].squeeze()
        print 'row 2:'
        print df.iloc[row+1].squeeze()
        print
    

    【讨论】:

    • 我希望有一个更“pythonic”的解决方案。这对我来说看起来像 for i in xrange(len(iterable)): print iterable[i]
    • @Lxndr 你的请求是以某种方式发给print,而这种方式使用pandas特定的方法来生成想要的输出
    【解决方案4】:

    您可以尝试iloc 索引。

    示例:

    for i in range(df.shape[0] - 1):                        
        idx1,idx2=i,i+1                         
        row1,row2=df.iloc[idx1],df.iloc[idx2]   
        print(row1)                             
        print(row2)                             
        print()                                                                            
    

    【讨论】:

    • 这和@zipa 的回答有同样的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2022-10-25
    • 2021-02-01
    • 2012-05-30
    • 2019-07-19
    相关资源
    最近更新 更多