如何在 pandas 中设置行的范围?

How to set ranges of rows in pandas?

我有以下工作代码,在 startsends.

指定的间隔指向的位置将 1 设置为“new_col”
import pandas as pd
import numpy as np


df = pd.DataFrame({"a": np.arange(10)})

starts = [1, 5, 8]
ends = [1, 6, 10]

value = 1
df["new_col"] = 0

for s, e in zip(starts, ends):
    df.loc[s:e, "new_col"] = value

print(df)
   a  new_col
0  0        0
1  1        1
2  2        0
3  3        0
4  4        0
5  5        1
6  6        1
7  7        0
8  8        1
9  9        1

我希望这些间隔来自另一个数据帧 pointer_df

如何对其进行矢量化?

pointer_df = pd.DataFrame({"starts": starts, "ends": ends})

尝试:

df.loc[pointer_df["starts"]:pointer_df["ends"], "new_col"] = 2
print(df)

显然不起作用并给出

    raise AssertionError("Start slice bound is non-scalar")
AssertionError: Start slice bound is non-scalar

编辑:

似乎所有答案都使用某种 pythonic for 循环。

问题是如何向量化上面的操作?

如果没有 for loops/list 的理解,这是不可能的吗?

你可以这样做:

pointer_df = pd.DataFrame({"starts": starts, "ends": ends})

rang = np.arange(len(df))
indices = [i for s, e in pointer_df.to_numpy() for i in rang[slice(s, e + 1, None)]]

df.loc[indices, 'new_col'] = value
print(df)

输出

   a  new_col
0  0        0
1  1        1
2  2        0
3  3        0
4  4        0
5  5        1
6  6        1
7  7        0
8  8        1
9  9        1

如果你想要一个不使用任何 for 循环或列表理解的方法,只依赖于 numpy,你可以这样做:

def indices(start, end, ma=10):
    limits = end + 1
    lens = np.where(limits < ma, limits, end) - start
    np.cumsum(lens, out=lens)
    i = np.ones(lens[-1], dtype=int)
    i[0] = start[0]
    i[lens[:-1]] += start[1:]
    i[lens[:-1]] -= limits[:-1]
    np.cumsum(i, out=i)
    return i


pointer_df = pd.DataFrame({"starts": starts, "ends": ends})
df.loc[indices(pointer_df.starts.values, pointer_df.ends.values, ma=len(df)), "new_col"] = value
print(df)

我根据此 answer 中的方法对您的用例进行了调整。

for i,j in zip(pointer_df["starts"],pointer_df["ends"]):
    print (i,j)

在你的字典上应用相同的方法