Ошибка запуска регрессии Тейла-Сен в Python - PullRequest
1 голос
/ 07 июня 2019

У меня есть датафрейм, похожий на следующий, который мы назовем "df":

id    value    time
a      1        1
a      1.5      2
a      2        3
a      2.5      4
b      1        1
b      1.5      2
b      2        3
b      2.5      4

Я запускаю различные регрессии по "id" в Python на этом фрейме данных. Как правило, для этого требуется группировка по «id», а затем применение функции к тем группировкам, которая вычисляет регрессию.

Я работаю с 2 подобными методами регрессии в библиотеке статистики Сципи:

  1. Оценка Тейл-Сена:

    (https://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.stats.mstats.theilslopes.html)

  2. Оценка Зигеля:

    (https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.siegelslopes.html).

Оба этих приема одинакового типа данных. Следовательно, функция для их вычисления должна быть такой же, как и для используемой техники.

Для Тейл-Сен я написал следующую функцию и оператор groupby, который будет применяться к этой функции:

def theil_reg(df, xcol, ycol):
   model = stats.theilslopes(ycol,xcol)
   return pd.Series(model)

out = df.groupby('id').apply(theil_reg, xcol='time', ycol='value')

Однако я получаю следующую ошибку, с которой мне было труднее всего понять, как обращаться:

ValueError: не удалось преобразовать строку в число с плавающей точкой: 'time'

Фактическая переменная time - объект с плавающей точкой, поэтому он не является строкой. Это заставляет меня поверить, что функция stats.theilslopes не распознает, что time является столбцом в кадре данных, и вместо этого использует 'time' в качестве строкового ввода в функцию.

Однако, если это так, то, похоже, это ошибка в пакете stats.theilslopes, и Scipy должен ее устранить. Я полагаю, что причина в том, что та же самая функция, что и выше, но вместо этого использует пакет siegelslopes, работает отлично и дает ожидаемый результат, и они по сути одинаковы с одинаковыми оценками. входы.

Выполнение следующих действий на Siegel:

def siegel_reg(df, xcol, ycol):
   model = stats.siegelslopes(ycol,xcol)
   return pd.Series(model)

out = df.groupby('id').apply(siegel_reg, xcol='time',ycol='value')

Не создает ошибок относительно переменной time и проводит регрессию по мере необходимости.

У кого-нибудь есть мысли о том, что я что-то здесь упускаю? Если так, я буду признателен за любые мысли, а если нет, за мысли о том, как решить эту проблему со Сципи.

Редактировать: вот полное сообщение об ошибке, которое появляется при запуске этого сценария:

ValueError Traceback (most recent call last)
C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in apply(self, func, *args, **kwargs)
    688 try:
--> 689 result = self._python_apply_general(f)
    690 except Exception:

C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in _python_apply_general(self, f)
    706 keys, values, mutated = self.grouper.apply(f, self._selected_obj,
--> 707                                                    self.axis)
    708 

C:\Anaconda\lib\site-packages\pandas\core\groupby\ops.py in apply(self, f, data, axis)
    189             group_axes = _get_axes(group)
--> 190             res = f(group)
    191             if not _is_indexed_like(res, group_axes):

C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in f(g)
    678                     with np.errstate(all='ignore'):
--> 679                         return func(g, *args, **kwargs)
    680             else:

<ipython-input-506-0a1696f0aecd> in theil_reg(df, xcol, ycol)
      1 def theil_reg(df, xcol, ycol):
----> 2     model = stats.theilslopes(ycol,xcol)
      3     return pd.Series(model)

C:\Anaconda\lib\site-packages\scipy\stats\_stats_mstats_common.py in 
theilslopes(y, x, alpha)
    221     else:
--> 222         x = np.array(x, dtype=float).flatten()
    223         if len(x) != len(y):

ValueError: could not convert string to float: 'time'

During handling of the above exception, another exception occurred:

ValueError Traceback (most recent call last)
<ipython-input-507-9a199e0ce924> in <module>
----> 1 df_accel_correct.groupby('chart').apply(theil_reg, xcol='time', 
ycol='value')

C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in apply(self, func, *args, **kwargs)
    699 
    700                 with _group_selection_context(self):
--> 701                     return self._python_apply_general(f)
    702 
    703         return result

C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in _python_apply_general(self, f)
    705     def _python_apply_general(self, f):
    706         keys, values, mutated = self.grouper.apply(f, 
self._selected_obj,
--> 707                                                    self.axis)
    708 
    709         return self._wrap_applied_output(

C:\Anaconda\lib\site-packages\pandas\core\groupby\ops.py in apply(self, f, data, axis)
    188             # group might be modified
    189             group_axes = _get_axes(group)
--> 190             res = f(group)
    191             if not _is_indexed_like(res, group_axes):
    192                 mutated = True

C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in f(g)
    677                 def f(g):
    678                     with np.errstate(all='ignore'):
--> 679                         return func(g, *args, **kwargs)
    680             else:
    681                 raise ValueError('func must be a callable if args or '

<ipython-input-506-0a1696f0aecd> in theil_reg(df, xcol, ycol)
      1 def theil_reg(df, xcol, ycol):
----> 2     model = stats.theilslopes(ycol,xcol)
      3     return pd.Series(model)

C:\Anaconda\lib\site-packages\scipy\stats\_stats_mstats_common.py in theilslopes(y, x, alpha)
    220         x = np.arange(len(y), dtype=float)
    221     else:
--> 222         x = np.array(x, dtype=float).flatten()
    223         if len(x) != len(y):
    224             raise ValueError("Incompatible lengths ! (%s<>%s)" % (len(y), len(x)))

ValueError: could not convert string to float: 'time'

Обновление 2: после вызова df в функции я получил следующее сообщение об ошибке:

ValueError                                Traceback (most recent call last)
C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in apply(self, func, *args, **kwargs)
    688             try:
--> 689                 result = self._python_apply_general(f)
    690             except Exception:

C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in _python_apply_general(self, f)
    706         keys, values, mutated = self.grouper.apply(f, self._selected_obj,
--> 707                                                    self.axis)
    708 

C:\Anaconda\lib\site-packages\pandas\core\groupby\ops.py in apply(self, f, data, axis)
    189             group_axes = _get_axes(group)
--> 190             res = f(group)
    191             if not _is_indexed_like(res, group_axes):

C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in f(g)
    678                     with np.errstate(all='ignore'):
--> 679                         return func(g, *args, **kwargs)
    680             else:

<ipython-input-563-5db69048f347> in theil_reg(df, xcol, ycol)
      1 def theil_reg(df, xcol, ycol):
----> 2     model = stats.theilslopes(df[ycol],df[xcol])
      3     return pd.Series(model)

C:\Anaconda\lib\site-packages\scipy\stats\_stats_mstats_common.py in theilslopes(y, x, alpha)
    248     sigma = np.sqrt(sigsq)
--> 249     Ru = min(int(np.round((nt - z*sigma)/2.)), len(slopes)-1)
    250     Rl = max(int(np.round((nt + z*sigma)/2.)) - 1, 0)

ValueError: cannot convert float NaN to integer

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
<ipython-input-564-d7794bd1d495> in <module>
----> 1 correct_theil = df_accel_correct.groupby('chart').apply(theil_reg, xcol='time', ycol='value')

C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in apply(self, func, *args, **kwargs)
    699 
    700                 with _group_selection_context(self):
--> 701                     return self._python_apply_general(f)
    702 
    703         return result

C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in _python_apply_general(self, f)
    705     def _python_apply_general(self, f):
    706         keys, values, mutated = self.grouper.apply(f, self._selected_obj,
--> 707                                                    self.axis)
    708 
    709         return self._wrap_applied_output(

C:\Anaconda\lib\site-packages\pandas\core\groupby\ops.py in apply(self, f, data, axis)
    188             # group might be modified
    189             group_axes = _get_axes(group)
--> 190             res = f(group)
    191             if not _is_indexed_like(res, group_axes):
    192                 mutated = True

C:\Anaconda\lib\site-packages\pandas\core\groupby\groupby.py in f(g)
    677                 def f(g):
    678                     with np.errstate(all='ignore'):
--> 679                         return func(g, *args, **kwargs)
    680             else:
    681                 raise ValueError('func must be a callable if args or '

<ipython-input-563-5db69048f347> in theil_reg(df, xcol, ycol)
       1 def theil_reg(df, xcol, ycol):
 ----> 2     model = stats.theilslopes(df[ycol],df[xcol])
       3     return pd.Series(model)

C:\Anaconda\lib\site-packages\scipy\stats\_stats_mstats_common.py in theilslopes(y, x, alpha)
    247     # Find the confidence interval indices in `slopes`
    248     sigma = np.sqrt(sigsq)
--> 249     Ru = min(int(np.round((nt - z*sigma)/2.)), len(slopes)-1)
    250     Rl = max(int(np.round((nt + z*sigma)/2.)) - 1, 0)
    251     delta = slopes[[Rl, Ru]]

ValueError: cannot convert float NaN to integer

Однако у меня нет нулевых значений ни в одном столбце, и оба столбца являются числами с плавающей запятой. Любые предложения по этой ошибке?

1 Ответ

1 голос
/ 10 июня 2019

По сути, вы передаете строковые значения имен столбцов (не любых объектов значений) в методы, но для вызовов slopes требуются массивы numpy (или ряды панд, которые могут быть преобразованы в массивы). В частности, вы пытаетесь выполнить этот вызов без ссылки на df , и, следовательно, ваша ошибка:

model = stats.theilslopes('value', 'time')

Просто укажите df в звонках:

model = stats.theilslopes(df['value'], df['time'])

model = stats.theilslopes(df[ycol], df[xcol])

Относительно разных результатов по пакетам не означает ошибок со Scipy. Пакеты запускаются в разных реализациях. Внимательно прочитайте документы, чтобы узнать, как вызывать методы. Возможно, другой пакет, на который вы ссылаетесь, позволяет вводить данные в качестве аргумента внутри вызова, а именованные строки ссылаются на столбцы, как показано ниже:

slopes_call(y='y_string', x='x_string', data=df)

В общем, объектная модель Python всегда требует явных именованных ссылок на вызовы и объекты и не принимает контекст.

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