Использование маскированных массивов с rpy2

1
import numpy
import rpy2
from rpy2 import robjects
import rpy2.robjects.numpy2ri

r = robjects.r
rpy2.robjects.numpy2ri.activate()

x = numpy.array( [1, 5, -99, 4, 5, 3, 7, -99, 6] )
mx = numpy.ma.masked_values( x, -99 )

print x         # works, displays all values
print r.sd(x)   # works, but uses -99 values in calculation

print mx        # works, now -99 values are masked (--)
print r.sd(mx)  # does not work - error

Я новый пользователь rpy2 и numpy. Я использую R 2.14.1, python 2.7.1, rpy2 2.2.5, numpy 1.5.1 на RHEL5.

Мне нужно прочитать данные в массив numpy и использовать на нем функции rpy2. Тем не менее, мне нужно маскировать отсутствующие значения перед использованием массива с rpy2.

У меня нет проблем с маскировкой значений, но я не могу заставить rpy2 работать с полученным массивом в масках. Похоже, может быть, преобразование numpy2ri не работает на маскированных массивах numpy? (см. ниже)

Как я могу сделать эту работу? Можно ли указать rpy2 игнорировать маскированные значения? Я хотел бы придерживаться R, а не использовать scipy/numpy напрямую, так как позже буду более продвинутым.

Благодарю.

Traceback (most recent call last):
  File "d.py", line 16, in <module>
    print r.sd(mx)  # does not work - error
  File "/dev/py/lib/python2.7/site-packages/rpy2-2.2.5dev_20120227-py2.7-linux-x86_64.egg/rpy2/robjects/functions.py", line 82, in __call__
    return super(SignatureTranslatedFunction, self).__call__(*args, **kwargs)
  File "/dev/py/lib/python2.7/site-packages/rpy2-2.2.5dev_20120227-py2.7-linux-x86_64.egg/rpy2/robjects/functions.py", line 30, in __call__
    new_args = [conversion.py2ri(a) for a in args]
  File "/dev/py/lib/python2.7/site-packages/rpy2-2.2.5dev_20120227-py2.7-linux-x86_64.egg/rpy2/robjects/numpy2ri.py", line 36, in numpy2ri
    vec = SexpVector(o.ravel("F"), _kinds[o.dtype.kind])
TypeError: ravel() takes exactly 1 argument (2 given)

Обновление. Поскольку rpy2 не может обрабатывать маскированные массивы numpy, я попытался преобразовать значения -99 в numpy NaN. По-видимому, rpy2 распознает numpy NaN-значения как значения NA в стиле R.

Код ниже работает, потому что в вызове r.sd() я могу указать rpy2 не использовать значения NA. Но начальная замена NaN определенно медленнее, чем применение маски numpy.

Может ли кто-нибудь из вас мастеров python дать мне более быстрый способ сделать -99 замену NaN на большое число ndarray? Или, может быть, предложить другой подход?

Благодарю.

# 'x' is a large numpy ndarray I am working with
# ('x' in the original code above was a small test array)

for i in range(900, 950):           # random slice of numpy ndarray
  for j in range(6225):             # full extent across slice
    if x[i][j] == -99:
      x[i][j] = numpy.NaN

y = x[933]                          # random piece of converted range
sd = r.sd( y, **{'na.rm': 'TRUE'} ) # r.sd() call that ignores numpy NaN values
print sd
Теги:
numpy
rpy2

2 ответа

2
Лучший ответ

Концепция "маскированных значений" (то есть массива значения, связанного с перечнем индексов, подлежащих маскировке) непосредственно не существует в R.

В значениях R либо устанавливаются как "отсутствующие" (NA), либо подмножество исходной структуры данных (так что создается новый объект, содержащий только это подмножество).

Теперь то, что происходит за сценой в rpy2 во время numpy to rinterface, заключается в том, что создается копия массива numpy в массив R (наоборот, выставляя массив R на numpy, необязательно требуется копирование). Нет никакой причины, по которой маски не будут обрабатываться на этом этапе (это может сделать путь к базе кода быстрее, если кто-то предоставляет патч). Альтернативой является создание массива numpy без замаскированных значений, затем подайте это на rpy2.

  • 0
    Проблема с извлечением значений -99 из массива numpy заключается в том, что мне нужно сохранить структуру массива. Я удивлен, что rpy2 не может работать с замаскированными массивами - может быть, это не то, что людям нужно делать очень часто? В любом случае, спасибо за ваш ответ.
  • 0
    Не понял, что вы разработчик rpy2. Спасибо, что предоставили это нам! Я хотел бы иметь возможность предоставить патч. Я обновил мой код выше с обходным путем, лучшее, что я могу придумать на данный момент.
Показать ещё 1 комментарий
1

Вы можете ускорить процесс замены значений -99 на NaN с помощью маскированных массивов, объектов, которые изначально определены в numpy.ma

как в следующем коде:

x_masked = numpy.ma.masked_array(x, mask= (x==-99) )
x_filled = x_masked.filled( numpy.NaN )

x_masked - numpy.ma (маскированный массив). x_filled - numpy.ndarray (обычный массив numpy)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню