web-dev-qa-db-ja.com

pandasデータフレームを使用した線形回帰

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

私がここでどこが間違っているのか誰か知っていますか?また、プロットに回帰直線を追加する方法もわかりません。私のコードに関する他の一般的なコメントも大歓迎です、私はまだ初心者です。

10
TimStuart

'#DIV/0!'を置き換える代わりに手作業で、データを強制的に数値にします。これは一度に2つのことを行います。結果が(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

これでエラーが修正されます。しかし、データに線を当てはめるという一般的なテーマについては、ポリフィットよりも好きな2つの方法を手元に置いています。 2つのうちの2つ目は、より堅牢です(そして、統計に関するより詳細な情報を返す可能性があります)が、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)
23
Dan Allan