将切片的DataFrame分配给另一个相同大小的切片DataFrame会产生:ValueError,与Series不兼容的索引器

时间:2018-05-18 23:13:26

标签: python pandas dataframe

我正在尝试将一个DataFrame(df2)中的标签应用到另一个(df1)条件中,并依赖于一个DataFrame列中的另一个值,以便在由一对列定义的区间内着陆在另一个Datarame中。

这是代码,

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赋值很接近,但是我输入了错误的元素类型,所以我不得不挤压它们。很高兴在这里获得原始类型。我也为一个专栏制作了示例,但实际上我正在复制我的源代码中两列的标签。

1 个答案:

答案 0 :(得分: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。尝试在数据框中将Series指定为值时发生错误。并df2.loc[ is_in_c1c2 , 'l' ].values返回ndarray。该数组只包含一个值,因为只有一个匹配,但理论上,可能有多个匹配。