分隔字符串列,将子值转换为浮点数并分配列标签

separating a string column, converting sub values into float and assigning column labels

我有一个 table t 和矢量时间。

sym vals           
-------------------
A   "3.6, 2.1, 1.8"
B   "2.1, 1.8, 1.6"
C   "2.2, 1.9, 1.6"
D   "1.9, 1.5, 1.3"
E   "2.6, 2.1, 1.9"

times: `0`1`2

我想将每行中的逗号分隔字符串分开并将每个值转换为浮点数。然后列标签需要是时间。我还想删除列 vals。以下语句执行此操作。

t_out: delete vals from t, 'flip exec times!("FFF";",")0:vals from t

sym 1   2   3  
---------------
A   3.6 2.1 1.8
B   2.1 1.8 1.6
C   2.2 1.9 1.6
D   1.9 1.5 1.3
E   2.6 2.1 1.9

为什么 exec times!("FFF";",")0:vals from t 在将值转换为浮点数后转置 table?为什么我们需要 'flip 而不仅仅是 flip?我感谢您的帮助。是否有其他方法可以实现此目的?

(这里有点猜测,因为你问的是 q 的设计选择。)

0: 通常用于读取 CSV 文件,其中每行存储一行,以逗号分隔。此行不会始终具有相同的类型,例如,这可能是 CSV 文件(以您的示例为基础):

3.6, 2.1, 1.8, 10
2.1, 1.8, 1.6, 20
2.2, 1.9, 1.6, 30
1.9, 1.5, 1.3, 40
2.6, 2.1, 1.9, 50

所以我们有四列,前三列是 float 列,第四列是 long (int) 列。

当您使用 0: 读取 CSV(或者在您的情况下,只是一个类似于 CSV 的字符串列表)时,q 将转置 table 以便您有一个列表包含四个列表。

q)vals: ("3.6, 2.1, 1.8, 10"; "2.1, 1.8, 1.6, 20"; "2.2, 1.9, 1.6, 30"; "1.9, 1.5, 1.3, 40"; "2.6, 2.1, 1.9, 50")
q)vals
"3.6, 2.1, 1.8, 10"
"2.1, 1.8, 1.6, 20"
"2.2, 1.9, 1.6, 30"
"1.9, 1.5, 1.3, 40"
"2.6, 2.1, 1.9, 50"
q)("FFFJ"; ",") 0: vals
3.6 2.1 2.2 1.9 2.6
2.1 1.8 1.9 1.5 2.1
1.8 1.6 1.6 1.3 1.9
10  20  30  40  50 

此列表中的四个列表中的每一个都将被正确键入:

q)first ("FFFJ"; ",") 0: vals
3.6 2.1 2.2 1.9 2.6
q)type first ("FFFJ"; ",") 0: vals
9h
q)last ("FFFJ"; ",") 0: vals
10 20 30 40 50
q)type last ("FFFJ"; ",") 0: vals
7h

这使得使用起来更容易,因为您没有混合列表的列表。备选方案是:

q)flip ("FFFJ"; ",") 0: vals
3.6 2.1 1.8 10
2.1 1.8 1.6 20
2.2 1.9 1.6 30
1.9 1.5 1.3 40
2.6 2.1 1.9 50
q)first flip ("FFFJ"; ",") 0: vals
3.6
2.1
1.8
10
q)type first flip ("FFFJ"; ",") 0: vals
0h

我猜这样做的原因是性能,因为在幕后,tables 实际上是列字典,所以实际上看起来像这样:

q)`1`2`3`4 ! ("FFFJ"; ",") 0: vals
1| 3.6 2.1 2.2 1.9 2.6
2| 2.1 1.8 1.9 1.5 2.1
3| 1.8 1.6 1.6 1.3 1.9
4| 10  20  30  40  50 

不过,你问的是 q 的设计选择,所以我只是猜测。

你需要使用 'flip 而不是 flip 的原因是你想连接两个 table 的每个元素(它们被视为字典列表)彼此,所以你正在使用每个迭代器。您可以阅读它 here(如果您稍微向下滚动到“高级部分,就在 each-left header 上方,它会更好地解释它)。

为了明确迭代器 ' 正在更改 , 而不是 flip,我会将您的查询写为:

... from t ,' flip exec ...

这更像是一种好奇心,但您可以通过使用 by 分组有效地强制“翻转”自然发生(即使按分组没有意义)

q)exec times!raze("FFF";",")0:vals by sym:sym from t
sym| 0   1   2
---| -----------
A  | 3.6 2.1 1.8
B  | 2.1 1.8 1.6
C  | 2.2 1.9 1.6
D  | 1.9 1.5 1.3
E  | 2.6 2.1 1.9

这也消除了 append-each (,') 到 sideways-join 结果

的需要