应用列操作以获取pandas中的新列

时间:2017-04-12 14:31:19

标签: python pandas numpy dataframe

我有这样的数据

ID    8-Jan 15-Jan  22-Jan  29-Jan  5-Feb   12-Feb  LowerBound   UpperBound
001    618    720    645     573     503     447       -             -
002    62     80      67      94      81      65       -             -      
003    32     10      23      26      26      31       -             -
004    22     13       1      28      19      25       -             -
005    9       7       9      6        8       4       -             -

我想使用95%置信区间为每个产品创建两个具有下限和上限的列。我知道编写循环遍历每个产品ID的函数的手动方式

import numpy as np
import scipy as sp
import scipy.stats

# Method copied from http://stackoverflow.com/questions/15033511/compute-a-confidence-interval-from-sample-data
def mean_confidence_interval(data, confidence=0.95):
    a = 1.0*np.array(data)
    n = len(a)
    m, se = np.mean(a), scipy.stats.sem(a)
    h = se * sp.stats.t._ppf((1+confidence)/2., n-1)
    return m-h, m+h

Pandas或(一种内衬类型的东西)有效吗?

3 个答案:

答案 0 :(得分:2)

当然,您需要df.apply。请注意,您需要修改mean_confidence_interval才能返回pd.Series([m-h, m+h])

df[['LowerBound','UpperBound']] = df.apply(mean_confidence_interval, axis=1)

答案 1 :(得分:2)

平均值的标准误差非常简单,因此您可以轻松地对此进行矢量化:

import scipy.stats as ss
df.mean(axis=1) + ss.t.ppf(0.975, df.shape[1]-1) * df.std(axis=1)/np.sqrt(df.shape[1])

会给你上限。使用- ss.t.ppf作为下限。

此外,熊猫似乎有一个sem method。如果您有一个大型数据集,我不建议使用apply over rows。这很慢。以下是一些时间安排:

df = pd.DataFrame(np.random.randn(100, 10))

%timeit df.apply(mean_confidence_interval, axis=1)
100 loops, best of 3: 18.2 ms per loop

%%timeit
dist = ss.t.ppf(0.975, df.shape[1]-1) * df.sem(axis=1)
mean = df.mean(axis=1)
mean - dist, mean + dist
1000 loops, best of 3: 598 µs per loop

答案 2 :(得分:0)

由于您已经创建了一个计算置信区间的函数,只需将其应用于数据的每一行:

def mean_confidence_interval(data):
  confidence = 0.95      
  m = data.mean()
  se = scipy.stats.sem(data)
  h = se * sp.stats.t._ppf((1 + confidence) / 2, data.shape[0] - 1)
  return pd.Series((m - h, m + h))

interval = df.apply(mean_confidence_interval, axis=1)
interval.columns = ("LowerBound", "UpperBound")
pd.concat([df, interval],axis=1)