使用 Pandas TimeSeries 编码变量

Posted

技术标签:

【中文标题】使用 Pandas TimeSeries 编码变量【英文标题】:Coding variables with Pandas TimeSeries 【发布时间】:2014-02-11 01:25:57 【问题描述】:

作为我在 previous question 中苦苦挣扎的事情的后续行动,我一直致力于分析来自 Pandas 中的鼠标跟踪实验的一些相当复杂的行为数据。

我的数据的一个相关子集如下所示:

data.iloc[0]

time_stamp                                     21/11/2013 13:06
subject                                                 1276270
trial                                                         0
stimuli                                                      14
resp                                                          2
rt                                                         1145
x             [-0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0....
y             [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, ...
t             [1, 26, 26, 35, 45, 55, 65, 75, 85, 95, 105, 1...
Name: 0, dtype: object

其中,xyt 是鼠标坐标和时间戳的 1D numpy 数组。

我想使用 Pandas 的大量时间序列数据资源,将这些坐标转换和分析为 TimeSeries 对象。将它们转换为 TimeSeries 对象(rxry,每个对象都具有通过将时间戳插入 20 毫秒间隔生成的索引。

data.rx.iloc[0]

0     -0
20     0
40     0
60     0
80     0
100    0
120    0
140    0
160    0
180    0
200    0
220    0
240    0
260    0
280    0
...
2720    1
2740    1
2760    1
2780    1
2800    1
2820    1
2840    1
2860    1
2880    1
2900    1
2920    1
2940    1
2960    1
2980    1
3000    1
Length: 151, dtype: float64

但是,这种方法,在 DataFrame 的每一行嵌套 2 个 TimeSeries,绝对不是惯用的(请参阅 this question);虽然我已经能够用它做很多事情了,但我觉得我在和 Pandas 作对,让自己过不下去。

我认为,正确的方法是将rxry 存储为独立的数据结构,或者在我现有的data 中添加302 列,rx 和@987654338 中的每个时间步都有一个列@。

第一种方法的问题是我无法访问我的分类数据(即subjectstimuliresp 列,以及我在这里遗漏的其他列),而问题第二个是我最终得到了 DataFrame 数千列宽(对于我应用的每个转换,我再次更宽:每一步的速度,每一步的角度等),并且没有访问特定时间序列的有用方法(即我目前一直称为data.rx.mean().plot()

所有这些实际上只是我的问题的序言,就是这样:

Pandas 或任何其他 python 库是否提供了一种处理大量时间序列数据的方法,同时保留伴随它们的编码数据?

谢谢,

欧因

【问题讨论】:

【参考方案1】:

有人通过电子邮件询问我是否找到了我想在这里做的事情的解决方案,所以我分享了我迄今为止一直在做的事情。这可能不是使用pandas 的规范方式,但对我来说已经足够了。

简而言之,我已将数据拆分为几个数据框。 第一个 data 同上,但我只使用与单个值对应的列,例如 trialstimuliresprt

对于我的时间序列数据,我使用了两个额外的数据框,一个用于 x 坐标数据,一个用于 y。虽然可能有一种更优雅的生成方式,但我的代码执行以下操作。

data.iloc[0]

    time_stamp                                     21/11/2013 13:06
    subject                                                 1276270
    trial                                                         0
    stimuli                                                      14
    resp                                                          2
    rt                                                         1145
    x             [-0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0....
    y             [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, ...
    t             [1, 26, 26, 35, 45, 55, 65, 75, 85, 95, 105, 1...
    Name: 0, dtype: object

data['nx'], data['ny'] = zip(*
     [even_time_steps(x, y, t)
     for x, y, t, in zip(data.x, data.y, data.t)])
     # Using function even_time_steps from package squeak
     # https://github.com/EoinTravers/Squeak 
     # Simpler applications could use
     # data['nx'] = [pd.TimeSeries(x) for y in data['x']]
     # data['ny'] = [pd.TimeSeries(x) for y in data['y']]

# Seperate DataFrames
nx = pd.concat(list(data.nx), axis=1).T
ny = pd.concat(list(data.ny), axis=1).T

# Remove redundant columns
redundant = ['nx', 'ny', 'x', 'y'] # etc...
data = data.drop(redundant, axis=1)

# Important - reindex data
data.index = range(len(data)) # 0, 1, 2, ..., len(data)

现在data 包含我所有的编码信息,nx 我所有的 x 坐标信息,ny 我的 y 坐标信息。

nx.head()

       0    1    2    3    4    5    6    7    8        9     ...          91
    0    0    0    0    0    0    0    0    0    0  0.00000   ...     0.953960   
    1    0    0    0    0    0    0    0    0    0  0.00099   ...     1.000000   
    2    0    0    0    0    0    0    0    0    0  0.00000   ...     1.010000   
    3    0    0    0    0    0    0    0    0    0  0.00000   ...     0.870396   
    4    0    0    0    0    0    0    0    0    0  0.00000   ...     1.000000   

             92        93        94       95        96   97   98   99   100  
    0  0.993564  1.000000  1.000000  1.00000  1.000000    1    1    1    1  
    1  1.000000  1.000000  1.000000  1.00000  1.000000    1    1    1    1  
    2  1.010000  1.008812  1.003960  1.00000  1.000000    1    1    1    1  
    3  0.906238  0.936931  0.973564  0.98604  0.993366    1    1    1    1  
    4  1.000000  1.000000  1.000000  1.00000  1.000000    1    1    1    1  

    [5 rows x 101 columns]

最后,选择xy数据的特定子集,根据data中存储的编码变量,我只取相关数据子集的index

subject1_index = data[data.subject==1].index
print subject1_index

    Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
    18, 19, 20,  21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
    36, 37, 38, 39], dtype='int64')

并使用iloc 方法选择nxny 的匹配子集。

sub1_x = nx.iloc[subject1_index]
sub1_y = ny.iloc[subject1_index]
for i in subject1_index:
    plt.plot(nx.iloc[i], ny.iloc[i], 'r', alpha=.3)
plt.plot(sub1_x.mean(), sub1_y.mean(), 'r', linewidth=2)


编辑:为了完整起见,请注意我的很多分析都需要很长时间 格式化数据(并在 R 中执行)。再次,可能会有更优雅的 这样做的方式(所以使用风险自负!),但我的代码是(注意,这是真实的代码,来自不同的数据集, 而且我没有费心更改变量名称以匹配原始示例):

# Long format data
wide_data = data.copy()
steps = nx.columns
for i in steps:
    wide_data['nx_%i' % i] = nx[i]
    wide_data['ny_%i' % i] = ny[i]

id_vars = ['subject_nr', 'condition', 'count_trial_sequence',
    'trial_id', 'choice', 'accuracy']

# Long data with 'nx' as the variable
long_data = pd.melt(wide_data, id_vars=id_vars, value_vars = ['nx_%i' % i for i in steps])
long_data['step'] = long_data.variable.map(lambda s: int(s[3:]))
long_data['nx'] = long_data.value

# Same with 'ny'
tmp_long = pd.melt(wide_data, id_vars=id_vars, value_vars = ['ny_%i' % i for i in steps])
# Combine in single data frame
long_data['ny'] = tmp_long['value']
del tmp_long

long_data = long_data.drop(['variable', 'value'], axis=1)
long_data.to_csv(os.path.join('data', 'long_data.csv'))

long_data.head()
Out[41]: 
       subject_nr      condition  count_trial_sequence  trial_id choice accuracy  
    0   505250022              A                     0        13   rsp1     True   
    1   505250022              A                     1        16   rsp1     True   
    2   505250022              B                     2         2   rsp2    False   
    3   505250022              B                     3         0   rsp1    False   
    4   505250022              C                     4        33   rsp2    False   

       step  nx  ny  
    0     0   0   0  
    1     0   0   0  
    2     0   0   0  
    3     0   0   0  
    4     0   0   0  

【讨论】:

以上是关于使用 Pandas TimeSeries 编码变量的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 fill_value 对 Pandas 中的 TimeSeries 重新采样?

使用 pandas TimeSeries 创建热图

pandas timeseries DF 切片和选择

将 Pandas TimeSeries 导入 MongoDB

pandas中没有了'rolling_mean' 'rolling_std'

pandas resample 重采样