Python 根据另一数据帧中的行范围添加/填充列
与pandas合作时,我将df1按时间样本进行索引:Python 根据另一数据帧中的行范围添加/填充列,python,pandas,Python,Pandas,与pandas合作时,我将df1按时间样本进行索引: data = '''\ time flags input 8228835.0 53153.0 32768.0 8228837.0 53153.0 32768.0 8228839.0 53153.0 32768.0 8228841.0 53153.0 32768.0 8228843.0 61345.0 32768.0''' fileobj = pd.compat.Str
data = '''\
time flags input
8228835.0 53153.0 32768.0
8228837.0 53153.0 32768.0
8228839.0 53153.0 32768.0
8228841.0 53153.0 32768.0
8228843.0 61345.0 32768.0'''
fileobj = pd.compat.StringIO(data)
df1 = pd.read_csv(fileobj, sep='\s+', index_col='time')
df2表示开始和结束的时间范围,以定义“检查”状态为真的范围:
data = '''\
check start end
20536 True 8228837 8228993
20576 True 8232747 8232869
20554 True 8230621 8230761
20520 True 8227351 8227507
20480 True 8223549 8223669
20471 True 8221391 8221553'''
fileobj = pd.compat.StringIO(data)
df2 = pd.read_csv(fileobj, sep='\s+')
我需要做的是在df1中添加一个“check”列,并用True值填写df2中定义的实际时间范围。其他的都应该是假的。一个例子是:
flags input check
time
8228835.0 53153.0 32768.0 False
8228837.0 53153.0 32768.0 True
8228839.0 53153.0 32768.0 True
8228841.0 53153.0 32768.0 True
8228843.0 61345.0 32768.0 True
....
8228994.0. 12424.0. 32768.0. False
我认为您可以使用
IntervalIndex
和loc
df2.index=pd.IntervalIndex.from_arrays(df2.start,df2.end,'both')
df2.loc[df.index]
Out[174]:
check start end
[1, 2] True 1 2
[4, 5] True 4 5
[7, 8] True 7 8
df['newcol']=df2.loc[df.index].check.values.tolist()
df
Out[176]:
flags input newcol
flags
2 2 32768.0 True
4 4 32768.0 True
7 7 32768.0 True
使用
any()
的列表理解。虽然没有关于实际性能的线索,但如果您能为我们运行%计时,那就太好了
df1['check'] = [any(start <= i <= end for start,end in
zip(df2['start'], df2['end'])) for i in df1.index]
print(df1)
您可以创建一个列表或范围,然后使用:
为什么8228835
为真?我在df2
中没有看到包含此数字的任何范围。可能只是一个类型错误。请更正我的输入错误。对于后来者,需要更新构成数据帧的部分。具体来说,使用“导入io”和“fileobj=io.StringIO(数据)”而不是“pd.compat.StringIO(数据)”,因为“AttributeError:module”“pandas.compat”没有属性“StringIO”。没想到你可以像这样链接范围,好家伙@温,这对我来说也是新闻。我只能假设链。每次调用from_iterable(ranges)
。因为它是一个迭代器,所以不能重用它,所以每次都使用一个新的迭代器。我希望有人使用这些解决方案,您的IntervalIndex
看起来很整洁!或者,更可能的是,正在进行一些列表转换,这是低效的:(@jpp-这对作业进行了一点修改。我编辑了你的答案,以匹配对我有效的答案。此示例数据上约180万行的墙时间为3.74秒。感谢你向我指出这个方向!@schwim,当然,我改进了你的编辑[因为在文档中不鼓励链式分配]。我在df2.loc[df.index]处得到KeyError
part.需要在这一点上多花点时间…好主意,谢谢!不幸的是,df1的行数超过了200万行。我将其缩短为10k行,这个循环用了43秒完成。结果与df2的范围不太匹配。
flags input check
time
8228835.0 53153.0 32768.0 False
8228837.0 53153.0 32768.0 True
8228839.0 53153.0 32768.0 True
8228841.0 53153.0 32768.0 True
8228843.0 61345.0 32768.0 True
from itertools import chain
df2 = df2[df2['check']]
ranges = map(range, df2['start'], df2['end'])
df1['check'] = df1.index.isin(chain.from_iterable(ranges))
print(df1)
flags input check
time
8228835.0 53153.0 32768.0 False
8228837.0 53153.0 32768.0 True
8228839.0 53153.0 32768.0 True
8228841.0 53153.0 32768.0 True
8228843.0 61345.0 32768.0 True