0

我正在尝试将一个 DataFrame ( df2) 中的标签应用到另一个 ( df1) 中,具体取决于一个 DataFrame 的列中的另一个值,以落在另一个 DataFrame 中的一对列定义的间隔内。

这是代码,

import pandas
import numpy

df1 = pandas.DataFrame( { 'a' : [1,2,3,4,5,6], 'b' : True } )
df2 = pandas.DataFrame( { 'c1':[ 2.0,3.1,5.2] , 'c2': [2.5,4.6,7.1] , 'l': ['x1','x2','x3'] } )

df1['l'] = numpy.NaN

for i in range( len( df1 ) ) :
    aVal = df1.loc[ df1.index[i] , 'a' ]
    is_in_c1c2 = ( df2['c1'] <= aVal ) & ( aVal < df2['c2'] )

    if is_in_c1c2.any() :
        df1.loc[ df1.index[i], 'l' ] = numpy.squeeze( df2.loc[ is_in_c1c2 , 'l' ].values )

        # df1.loc[ df1.index[i], 'l' ] = df2.loc[ is_in_c1c2 , 'l' ] # ValueError, Incompatible indexer with Series


print( df1 )
print( df1['l'].map(type) )

>>>
   a     b    l
0  1  True  NaN
1  2  True   x1
2  3  True  NaN
3  4  True   x2
4  5  True  NaN
5  6  True   x3
0            <type 'float'>
1    <type 'numpy.ndarray'>
2            <type 'float'>
3    <type 'numpy.ndarray'>
4            <type 'float'>
5    <type 'numpy.ndarray'>
Name: l, dtype: object

我很惊讶在我第一次尝试时发现了异常ValueError, Incompatible indexer with Series。为什么不支持,这是 DataFrames 索引不匹配的结果还是究竟是什么?

是否有更清洁/矢量化的方式来执行此类操作?.values任务很接近,但给我留下了错误的元素类型,所以我不得不挤压它们。在这里获得原始类型会很好。我还为一列做了示例,但实际上我是从源中的两列复制标签。

4

1 回答 1

1

一种方法是使用 Pandas 的IntervalIndex.

idx = pd.IntervalIndex.from_arrays(df2['c1'], df2['c2'], closed='both')
df1['l'] = df2.loc[idx.get_indexer(df1['a']), 'l'].values
df1
>>>
    a   b       l
0   1   True    NaN
1   2   True    x1
2   3   True    NaN
3   4   True    x2
4   5   True    NaN
5   6   True    x3

不知道这有多快。如果df1['a']真的只包含整数,那么有一种更快的方法可以做到这一点。

我认为您的原件ValueError是因为df2.loc[ is_in_c1c2 , 'l' ]返回一个Series. 尝试将 a 分配Series为数据框中的值时会发生错误。并df2.loc[ is_in_c1c2 , 'l' ].values返回一个ndarray. 该数组仅包含一个值,因为只有一个匹配项,但理论上可能存在多个匹配项。

于 2018-05-19T01:00:18.940 回答