尝试将 pandas df 转换为 np 数组,dtaidistance 改为计算列表
Trying to convert pandas df to np array, dtaidistance computes list instead
我正在尝试计算从 pandas 转换而来的 ndarray 的距离矩阵。我尝试将 pandas df 当前转换为这种格式:
move_df =
movement
0 [4, 3, 6, 2]
1 [5, 2, 3, 6, 2]
2 [4, 7, 2, 3, 6, 1]
3 [4, 4, 4, 3]
... ...
33410 [2, 6, 3, 1, 8]
[33410 x 1 columns]
通过使用以下内容到 numpy ndarray:
1) m = move_df.to_numpy()
2) m = pd.DataFrame(move_df.tolist()).values
3) m = [move_df.tolist() for i in move_df.columns]
这些转换中的每一个都会产生一个这种格式的 numpy 数组:
[[list([4, 3, 6, 2])]
[list([5, 2, 3, 6, 2])]
[list([4, 7, 2, 3, 6, 1])]
[list([4, 4, 4, 3])]
...
[list([2, 6, 3, 1, 8])]]
因此,当我尝试 运行 dtaidistance 矩阵时,出现以下错误:
d_m = dtw.distance_matrix(m)
TypeError: unsupported operand type(s) for -: 'list' and 'list'
但是,当我通过复制和粘贴使用上述任何方法创建的几个 numpy 数组来创建列表列表时,代码有效。但这在 long 运行 中是不可行的,因为数组超过 30k 行。在从 pandas df 到 numpy 数组的转换中我做错了什么吗?我用了
print(type(m))
它输出它是一个 numpy 数组,我已经知道我不能从列表中减去一个列表,因此出现错误。
编辑:
对于 move_df.head(10).to_dict()
{'movement': {0: [4, 3, 6, 2],
1: [5, 2, 3, 6, 2],
2: [4, 7, 2, 3, 6, 1],
3: [4, 4, 4, 3],
4: [3, 6, 2, 3, 3],
5: [6, 2, 1],
6: [1, 1, 1, 1],
7: [7, 2, 3, 1, 1],
8: [7, 2, 3, 2, 1],
9: [6, 2, 3, 1]}}
假设你想用长度为 4 的列表组成一个数组:
m = df['movement'].str.len().eq(4)
a = np.array(df.loc[m, 'movement'].to_list())
输出:
array([[4, 3, 6, 2],
[4, 4, 4, 3],
[1, 1, 1, 1],
[6, 2, 3, 1]])
使用的输入:
df = pd.DataFrame({'movement': [[4, 3, 6, 2],
[5, 2, 3, 6, 2],
[4, 7, 2, 3, 6, 1],
[4, 4, 4, 3],
[3, 6, 2, 3, 3],
[6, 2, 1],
[1, 1, 1, 1],
[7, 2, 3, 1, 1],
[7, 2, 3, 2, 1],
[6, 2, 3, 1]]})
使用以下方法创建的数据框:
In [112]: df = pd.DataFrame({'movement': {0: [4, 3, 6, 2],
...: 1: [5, 2, 3, 6, 2],
...: 2: [4, 7, 2, 3, 6, 1],
...: 3: [4, 4, 4, 3],
...: 4: [3, 6, 2, 3, 3],
...: 5: [6, 2, 1],
...: 6: [1, 1, 1, 1],
...: 7: [7, 2, 3, 1, 1],
...: 8: [7, 2, 3, 2, 1],
...: 9: [6, 2, 3, 1]}})
有一个包含列表的 object
dtype 列。从该列派生的数组是 object
dtype:
In [121]: arr = df['movement'].to_numpy()
In [122]: arr
Out[122]:
array([list([4, 3, 6, 2]), list([5, 2, 3, 6, 2]),
list([4, 7, 2, 3, 6, 1]), list([4, 4, 4, 3]),
list([3, 6, 2, 3, 3]), list([6, 2, 1]), list([1, 1, 1, 1]),
list([7, 2, 3, 1, 1]), list([7, 2, 3, 2, 1]), list([6, 2, 3, 1])],
dtype=object)
通过选择列,我得到一个一维数组,而不是你得到的二维数组。其他都一样
这不能转换成二维数字数据类型数组。对于大多数用途,我们可以将其视为列表列表。
In [123]: arr.tolist()
Out[123]:
[[4, 3, 6, 2],
[5, 2, 3, 6, 2],
[4, 7, 2, 3, 6, 1],
[4, 4, 4, 3],
[3, 6, 2, 3, 3],
[6, 2, 1],
[1, 1, 1, 1],
[7, 2, 3, 1, 1],
[7, 2, 3, 2, 1],
[6, 2, 3, 1]]
如果列表的长度都相同,或者如果我们选择一个子集,则可以构造一个二维数组:
In [125]: arr[[0,3,6,9]]
Out[125]:
array([list([4, 3, 6, 2]), list([4, 4, 4, 3]), list([1, 1, 1, 1]),
list([6, 2, 3, 1])], dtype=object)
In [126]:
In [126]: np.stack(arr[[0,3,6,9]])
Out[126]:
array([[4, 3, 6, 2],
[4, 4, 4, 3],
[1, 1, 1, 1],
[6, 2, 3, 1]])
填充和切片也可用于强制列表匹配长度 - 但这可能意味着丢失信息。
但是不知道 dtw.distance_matrix
期望什么(看起来它想要一个二维数值数组),或者这些列表代表什么,我不能更进一步。
基本点是您的数据框包含长度不同的列表。
(此处为 dtaidistance 作者之一)
dtaidistance 包需要三种格式之一:
- 一个二维 numpy 数组(根据定义,所有序列的长度都相同)
- 一维 numpy.array 或 array.array 的 Python 列表。
- Python 个 Python 个列表
在你的情况下你可以这样做:
series = move_df['movement'].to_list()
dtw.distance_matrix(series)
然后在列表列表上工作。
要使用快速 C 实现,需要一个数组(Numpy 或 std lib 数组)。如果你想保持不同的长度,你可以这样做
series = move_df['movement'].apply(lambda a: np.array(a, dtype=np.double)).to_list()
dtw.distance_matrix_fast(series)
请注意,在您的 move_df 数据结构上就地执行应用操作可能是有意义的,这样您只需执行一次,而无需跟踪两个几乎相同的数据结构。执行此操作后,to_list 调用就足够了。因此:
move_df['movement'] = move_df['movement'].apply(lambda a: np.array(a, dtype=np.double))
series = move_df['movement'].to_list()
dtw.distance_matrix_fast(series)
如果你想使用 2D numpy 矩阵,你需要截断或填充所有系列,使其与其他答案中解释的长度相同(因为 dtw 填充更常见,不会丢失信息)。
ps。这假设你想做单变量 DTW,多变量时间序列的 ndim
子包需要不同的数据结构。
我正在尝试计算从 pandas 转换而来的 ndarray 的距离矩阵。我尝试将 pandas df 当前转换为这种格式:
move_df =
movement
0 [4, 3, 6, 2]
1 [5, 2, 3, 6, 2]
2 [4, 7, 2, 3, 6, 1]
3 [4, 4, 4, 3]
... ...
33410 [2, 6, 3, 1, 8]
[33410 x 1 columns]
通过使用以下内容到 numpy ndarray:
1) m = move_df.to_numpy()
2) m = pd.DataFrame(move_df.tolist()).values
3) m = [move_df.tolist() for i in move_df.columns]
这些转换中的每一个都会产生一个这种格式的 numpy 数组:
[[list([4, 3, 6, 2])]
[list([5, 2, 3, 6, 2])]
[list([4, 7, 2, 3, 6, 1])]
[list([4, 4, 4, 3])]
...
[list([2, 6, 3, 1, 8])]]
因此,当我尝试 运行 dtaidistance 矩阵时,出现以下错误:
d_m = dtw.distance_matrix(m)
TypeError: unsupported operand type(s) for -: 'list' and 'list'
但是,当我通过复制和粘贴使用上述任何方法创建的几个 numpy 数组来创建列表列表时,代码有效。但这在 long 运行 中是不可行的,因为数组超过 30k 行。在从 pandas df 到 numpy 数组的转换中我做错了什么吗?我用了
print(type(m))
它输出它是一个 numpy 数组,我已经知道我不能从列表中减去一个列表,因此出现错误。
编辑:
对于 move_df.head(10).to_dict()
{'movement': {0: [4, 3, 6, 2],
1: [5, 2, 3, 6, 2],
2: [4, 7, 2, 3, 6, 1],
3: [4, 4, 4, 3],
4: [3, 6, 2, 3, 3],
5: [6, 2, 1],
6: [1, 1, 1, 1],
7: [7, 2, 3, 1, 1],
8: [7, 2, 3, 2, 1],
9: [6, 2, 3, 1]}}
假设你想用长度为 4 的列表组成一个数组:
m = df['movement'].str.len().eq(4)
a = np.array(df.loc[m, 'movement'].to_list())
输出:
array([[4, 3, 6, 2],
[4, 4, 4, 3],
[1, 1, 1, 1],
[6, 2, 3, 1]])
使用的输入:
df = pd.DataFrame({'movement': [[4, 3, 6, 2],
[5, 2, 3, 6, 2],
[4, 7, 2, 3, 6, 1],
[4, 4, 4, 3],
[3, 6, 2, 3, 3],
[6, 2, 1],
[1, 1, 1, 1],
[7, 2, 3, 1, 1],
[7, 2, 3, 2, 1],
[6, 2, 3, 1]]})
使用以下方法创建的数据框:
In [112]: df = pd.DataFrame({'movement': {0: [4, 3, 6, 2],
...: 1: [5, 2, 3, 6, 2],
...: 2: [4, 7, 2, 3, 6, 1],
...: 3: [4, 4, 4, 3],
...: 4: [3, 6, 2, 3, 3],
...: 5: [6, 2, 1],
...: 6: [1, 1, 1, 1],
...: 7: [7, 2, 3, 1, 1],
...: 8: [7, 2, 3, 2, 1],
...: 9: [6, 2, 3, 1]}})
有一个包含列表的 object
dtype 列。从该列派生的数组是 object
dtype:
In [121]: arr = df['movement'].to_numpy()
In [122]: arr
Out[122]:
array([list([4, 3, 6, 2]), list([5, 2, 3, 6, 2]),
list([4, 7, 2, 3, 6, 1]), list([4, 4, 4, 3]),
list([3, 6, 2, 3, 3]), list([6, 2, 1]), list([1, 1, 1, 1]),
list([7, 2, 3, 1, 1]), list([7, 2, 3, 2, 1]), list([6, 2, 3, 1])],
dtype=object)
通过选择列,我得到一个一维数组,而不是你得到的二维数组。其他都一样
这不能转换成二维数字数据类型数组。对于大多数用途,我们可以将其视为列表列表。
In [123]: arr.tolist()
Out[123]:
[[4, 3, 6, 2],
[5, 2, 3, 6, 2],
[4, 7, 2, 3, 6, 1],
[4, 4, 4, 3],
[3, 6, 2, 3, 3],
[6, 2, 1],
[1, 1, 1, 1],
[7, 2, 3, 1, 1],
[7, 2, 3, 2, 1],
[6, 2, 3, 1]]
如果列表的长度都相同,或者如果我们选择一个子集,则可以构造一个二维数组:
In [125]: arr[[0,3,6,9]]
Out[125]:
array([list([4, 3, 6, 2]), list([4, 4, 4, 3]), list([1, 1, 1, 1]),
list([6, 2, 3, 1])], dtype=object)
In [126]:
In [126]: np.stack(arr[[0,3,6,9]])
Out[126]:
array([[4, 3, 6, 2],
[4, 4, 4, 3],
[1, 1, 1, 1],
[6, 2, 3, 1]])
填充和切片也可用于强制列表匹配长度 - 但这可能意味着丢失信息。
但是不知道 dtw.distance_matrix
期望什么(看起来它想要一个二维数值数组),或者这些列表代表什么,我不能更进一步。
基本点是您的数据框包含长度不同的列表。
(此处为 dtaidistance 作者之一)
dtaidistance 包需要三种格式之一:
- 一个二维 numpy 数组(根据定义,所有序列的长度都相同)
- 一维 numpy.array 或 array.array 的 Python 列表。
- Python 个 Python 个列表
在你的情况下你可以这样做:
series = move_df['movement'].to_list()
dtw.distance_matrix(series)
然后在列表列表上工作。
要使用快速 C 实现,需要一个数组(Numpy 或 std lib 数组)。如果你想保持不同的长度,你可以这样做
series = move_df['movement'].apply(lambda a: np.array(a, dtype=np.double)).to_list()
dtw.distance_matrix_fast(series)
请注意,在您的 move_df 数据结构上就地执行应用操作可能是有意义的,这样您只需执行一次,而无需跟踪两个几乎相同的数据结构。执行此操作后,to_list 调用就足够了。因此:
move_df['movement'] = move_df['movement'].apply(lambda a: np.array(a, dtype=np.double))
series = move_df['movement'].to_list()
dtw.distance_matrix_fast(series)
如果你想使用 2D numpy 矩阵,你需要截断或填充所有系列,使其与其他答案中解释的长度相同(因为 dtw 填充更常见,不会丢失信息)。
ps。这假设你想做单变量 DTW,多变量时间序列的 ndim
子包需要不同的数据结构。