Назначение нарезанного DataFrame в другой нарезанный DataFrame того же размера дает: ValueError, Несовместимый индексатор с сериями - PullRequest
0 голосов
/ 19 мая 2018

Я пытаюсь применить метки из одного 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 голосов
/ 19 мая 2018

Один из подходов заключается в использовании 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.Массив содержит только одно значение, поскольку существует только одно совпадение, но теоретически может быть несколько совпадений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...