Python 根据另一数据帧中的行范围添加/填充列

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

与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.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