快速方式将float类型的多个列组合成一个类型为array(float)的列

时间:2017-05-03 22:38:53

标签: pandas

我有这样的数据集:

df = pd.DataFrame({
    "333-0": [123,123,123],
    "5985-0.0": [1,2,3],
    "5985-0.1":[1,2,3],
    "5985-0.2":[1,2,3]  
     },
     index = [0,1,2] )

在这里,我们有三列["5985-0.0", "5985-0.1", "5985-0.2"]代表事物5985-0的第一,第二和第三个浮点读数 - 即.x表示数组索引。

我想把多个列并将它们折叠成一个包含某种float列表的5985-0列,我可以这样做:

srccols = ["5985-0.0", "5985-0.1", "5985-0.2"]
df["5985-0"] = df[srccols].apply(tuple, axis=1)
df.dropna(srccols, axis=1)

   333-0     5985-0
0    123  (1, 1, 1)
1    123  (2, 2, 2)
2    123  (3, 3, 3)

然后我可以将其存储为带有数组列的SQL表。

然而,apply(元组)非常慢。是否有更快,更惯用的pandas方法将多个列合并为一个。

(第一个说“正常化”的人得到了一个downvote)。

1 个答案:

答案 0 :(得分:1)

我的选择
假设我知道列

thing = '5985-0'
cols = ['5985-0.0', '5985-0.1', '5985-0.2']
k = len(cols)
v = df.values
l = [v[:, df.columns.get_loc(c)].tolist() for c in cols]
s = pd.Series(list(zip(*l)), name=thing)
df.drop(cols, 1).join(s)

   333-0     5985-0
0    123  (1, 1, 1)
1    123  (2, 2, 2)
2    123  (3, 3, 3)

基本案例
使用filterjoinapply(tuple, 1)

thing = '5985-0'
d = df.filter(like=thing)
s = d.apply(tuple, 1).rename(thing)
cols = d.columns
df.drop(cols, 1).join(s)

   333-0     5985-0
0    123  (1, 1, 1)
1    123  (2, 2, 2)
2    123  (3, 3, 3)

选项2
使用filterjoinpd.Series

thing = '5985-0'
d = df.filter(like=thing)
s = pd.Series(d.values.tolist(), name=thing)
cols = d.columns
df.drop(cols, 1).join(s)

   333-0     5985-0
0    123  [1, 1, 1]
1    123  [2, 2, 2]
2    123  [3, 3, 3]

选项3
使用filterjoinpd.Serieszip

thing = '5985-0'
d = df.filter(like=thing)
s = pd.Series(list(zip(*d.values.T)), name=thing)
cols = d.columns
print(df.drop(cols, 1).join(s))  
   333-0     5985-0
0    123  (1, 1, 1)
1    123  (2, 2, 2)
2    123  (3, 3, 3)

<强> 时序
大数据集

df = pd.concat([df] * 10000, ignore_index=True

%%timeit
thing = '5985-0'
d = df.filter(like=thing)
s = d.apply(tuple, 1).rename(thing)
cols = d.columns
df.drop(cols, 1).join(s)
1 loop, best of 3: 350 ms per loop

%%timeit
thing = '5985-0'
cols = ['5985-0.0', '5985-0.1', '5985-0.2']
k = len(cols)
v = df.values
l = [v[:, df.columns.get_loc(c)].tolist() for c in cols]
s = pd.Series(list(zip(*l)), name=thing)
df.drop(cols, 1).join(s)
100 loops, best of 3: 4.06 ms per loop

%%timeit
thing = '5985-0'
d = df.filter(like=thing)
s = pd.Series(d.values.tolist(), name=thing)
cols = d.columns
df.drop(cols, 1).join(s)
100 loops, best of 3: 4.56 ms per loop

%%timeit
thing = '5985-0'
d = df.filter(like=thing)
s = pd.Series(list(zip(*d.values.T)), name=thing)
cols = d.columns
df.drop(cols, 1).join(s)
100 loops, best of 3: 6.89 ms per loop