我试图根据值列表对数据帧进行切片,我该怎么做?
假设我有一个列表l,它看起来像:[0,1,0,0,1,1,0,0,0,1]
我希望返回数据框中的所有行,df,基于列表中的值是否为1.在此示例中,我将包括index为1,4,5和9的行。任何简单的方法去做这个?请道歉,如果这是一个简单的问题,但我仍然习惯于数据帧。
答案 0 :(得分:17)
您可以在此处使用遮罩:
df[np.array([0,1,0,0,1,1,0,0,0,1],dtype=bool)]
因此我们构造一个带有true和false的布尔数组。数组为True的每个位置都是我们选择的行。
请注意我们不过滤到位。为了检索结果,您必须将结果分配给(可选地不同的)变量:
df2 = df[np.array([0,1,0,0,1,1,0,0,0,1],dtype=bool)]
答案 1 :(得分:13)
将列表转换为布尔数组,然后使用布尔索引:
df = pd.DataFrame(np.random.randint(10, size=(10, 3)))
df[np.array(lst).astype(bool)]
Out:
0 1 2
1 8 6 3
4 2 7 3
5 7 2 3
9 1 3 4
答案 2 :(得分:11)
<强>设置强>
借用了@ ayhan的设置
df = pd.DataFrame(np.random.randint(10, size=(10, 3)))
没有numpy
不是最快的,但它拥有自己的,绝对是最短的。
df[list(map(bool, lst))]
0 1 2
1 3 5 6
4 6 3 2
5 5 7 6
9 0 0 1
计时
results.div(results.min(1), 0).round(2).pipe(lambda d: d.assign(Best=d.idxmin(1)))
ayh wvo pir mxu wen Best
N
1 1.53 1.00 1.02 4.95 2.61 wvo
3 1.06 1.00 1.04 5.46 2.84 wvo
10 1.00 1.00 1.00 4.30 2.73 ayh
30 1.00 1.05 1.24 4.06 3.76 ayh
100 1.16 1.00 1.19 3.90 3.53 wvo
300 1.29 1.00 1.32 2.50 2.38 wvo
1000 1.54 1.00 2.19 2.24 3.85 wvo
3000 1.39 1.00 2.17 1.81 4.55 wvo
10000 1.22 1.00 2.21 1.35 4.36 wvo
30000 1.19 1.00 2.26 1.39 5.36 wvo
100000 1.19 1.00 2.19 1.31 4.82 wvo
fig, (a1, a2) = plt.subplots(2, 1, figsize=(6, 6))
results.plot(loglog=True, lw=3, ax=a1)
results.div(results.min(1), 0).round(2).plot.bar(logy=True, ax=a2)
fig.tight_layout()
测试代码
ayh = lambda d, l: d[np.array(l).astype(bool)]
wvo = lambda d, l: d[np.array(l, dtype=bool)]
pir = lambda d, l: d[list(map(bool, l))]
wen = lambda d, l: d.loc[[i for i, x in enumerate(l) if x == 1], :]
def mxu(d, l):
a = np.array(l)
return d.query('@a != 0')
results = pd.DataFrame(
index=pd.Index([1, 3, 10, 30, 100, 300,
1000, 3000, 10000, 30000, 100000], name='N'),
columns='ayh wvo pir mxu wen'.split(),
dtype=float
)
for i in results.index:
d = pd.concat([df] * i, ignore_index=True)
l = lst * i
for j in results.columns:
stmt = '{}(d, l)'.format(j)
setp = 'from __main__ import d, l, {}'.format(j)
results.set_value(i, j, timeit(stmt, setp, number=10))
答案 3 :(得分:7)
In [181]: a = np.array(lst)
In [182]: df.query("index * @a > 0")
Out[182]:
0 1 2
1 1 5 5
4 0 2 0
5 4 9 9
9 2 2 5
或much better variant from @ayhan:
In [183]: df.query("@a != 0")
Out[183]:
0 1 2
1 1 5 5
4 0 2 0
5 4 9 9
9 2 2 5
PS我还借用了@Ayhan的设置
答案 4 :(得分:4)
或者可能会在list
中找到1的位置并从Dataframe
df.loc[[i for i,x in enumerate(lst) if x == 1],:]
答案 5 :(得分:1)
选择使用布尔列表是itertools.compress
做得很好的事。
鉴于
>>> df = pd.DataFrame(np.random.randint(10, size=(10, 2)))
>>> selectors = [0, 1, 0, 0, 1, 1, 0, 0, 0, 1]
代码
>>> selected_idxs = list(itertools.compress(df.index, selectors)) # [1, 4, 5, 9]
>>> df.iloc[selected_idxs, :]
0 1
1 1 9
4 3 4
5 4 1
9 8 9