Линейная регрессия с фреймом данных pandas
у меня есть фрейм данных в панд, который я использую для создания диаграммы рассеяния, и хочу включить линию регрессии для графика. Сейчас я пытаюсь сделать это с помощью polyfit.
вот мой код:
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
from numpy import *
table1 = pd.DataFrame.from_csv('upregulated_genes.txt', sep='t', header=0, index_col=0)
table2 = pd.DataFrame.from_csv('misson_genes.txt', sep='t', header=0, index_col=0)
table1 = table1.join(table2, how='outer')
table1 = table1.dropna(how='any')
table1 = table1.replace('#DIV/0!', 0)
# scatterplot
plt.scatter(table1['log2 fold change misson'], table1['log2 fold change'])
plt.ylabel('log2 expression fold change')
plt.xlabel('log2 expression fold change Misson et al. 2005')
plt.title('Root Early Upregulated Genes')
plt.axis([0,12,-5,12])
# this is the part I'm unsure about
regres = polyfit(table1['log2 fold change misson'], table1['log2 fold change'], 1)
plt.show()
но я получаю следующую ошибку:
TypeError: cannot concatenate 'str' and 'float' objects
кто-нибудь знает, где я буду неправильно здесь? Я также не уверен, как добавить линию регрессии к моему сюжету. Любые другие общие комментарии к моему коду также были бы чрезвычайно оценены, я все еще начинающий.
1 ответов
вместо замены ' #DIV / 0!- вручную заставьте данные быть числовыми. Это делает две вещи сразу: это гарантирует, что результат является числовым типом (не str), и он заменяет NaN
для любых записей, которые не могут быть проанализированы как число. Пример:
In [5]: Series([1, 2, 'blah', '#DIV/0!']).convert_objects(convert_numeric=True)
Out[5]:
0 1
1 2
2 NaN
3 NaN
dtype: float64
это должно исправить ваши ошибки. Но, по общему вопросу подгонки линии к данным, я держу под рукой два способа сделать это, которые мне нравятся больше, чем polyfit. Второй из двух является более надежным (и потенциально может вернуться гораздо более подробная информация о статистике), но для этого требуется statsmodels.
from scipy.stats import linregress
def fit_line1(x, y):
"""Return slope, intercept of best fit line."""
# Remove entries where either x or y is NaN.
clean_data = pd.concat([x, y], 1).dropna(0) # row-wise
(_, x), (_, y) = clean_data.iteritems()
slope, intercept, r, p, stderr = linregress(x, y)
return slope, intercept # could also return stderr
import statsmodels.api as sm
def fit_line2(x, y):
"""Return slope, intercept of best fit line."""
X = sm.add_constant(x)
model = sm.OLS(y, X, missing='drop') # ignores entires where x or y is NaN
fit = model.fit()
return fit.params[1], fit.params[0] # could also return stderr in each via fit.bse
чтобы построить его, сделайте что-то вроде
m, b = fit_line2(x, y)
N = 100 # could be just 2 if you are only drawing a straight line...
points = np.linspace(x.min(), x.max(), N)
plt.plot(points, m*points + b)