如何在 pandas 中设置行的范围?
How to set ranges of rows in pandas?
我有以下工作代码,在 starts
和 ends
.
指定的间隔指向的位置将 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)
在你的字典上应用相同的方法
我有以下工作代码,在 starts
和 ends
.
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)
在你的字典上应用相同的方法