我已经输入了如下的pandas数据框。 “ index_vec”列中的内容为字符串类型。
我想添加一组列,这些列的名称表示“ index_vec”列中的值,而值表示“ index_vec”中该值的计数。一个例子如下:
它显示'-1'列的第0行增加了1,并且'-2'列的第2行也增加了1。请注意,由于数据框的大小,有许多未显示的列。我有以下代码,想知道如何进一步提高执行速度。
for i in range (neg_index, pos_index):
df[str(i)]= 0
df[str(i)]= df[str(i)].astype(np.int16)
def add_counts(x):
# take the string rep of the list and make it into an actual python list of strings
index_vec = [str(x) for x in ast.literal_eval(x['index_vec'])]
x[set(index_vec)] = x[set(index_vec)] + [index_vec.count(i) for i in set(index_vec)]
return x
df=df.apply(add_counts, axis = 1)
答案 0 :(得分:1)
实际上可以在一个衬套中完成!
您的数据框如下所示:
df = pd.DataFrame({'index_vec': ["[370, -1, -1]", "[1201, 1201]", "[-2, 676, 676]", "[641, 641]", "[811, 811]"]})
index_vec
0 [370, -1, -1]
1 [1201, 1201]
2 [-2, 676, 676]
3 [641, 641]
4 [811, 811]
我们可以将转换索引向量列拆分为pd.Series
并应用value_counts
,这将创建您需要的所有列以及它们在每行中的计数。然后,我们将新的df与旧的df结合在一起:
df.join(df['index_vec'].str.strip("[]").str.split(", ").apply(pd.Series.value_counts).fillna(0).astype(np.int16))
输出:
index_vec -1 370 1201 676 -2 641 811
0 [370, -1, -1] 2.0 1.0 0.0 0.0 0.0 0.0 0.0
1 [1201, 1201] 0.0 0.0 2.0 0.0 0.0 0.0 0.0
2 [-2, 676, 676] 0.0 0.0 0.0 2.0 1.0 0.0 0.0
3 [641, 641] 0.0 0.0 0.0 0.0 0.0 2.0 0.0
4 [811, 811] 0.0 0.0 0.0 0.0 0.0 0.0 2.0
完整代码:
import pandas as pd
import numpy as np
df = pd.DataFrame({'index_vec': ["[370, -1, -1]", "[1201, 1201]", "[-2, 676, 676]", "[641, 641]", "[811, 811]"]})
df = df.join(df['index_vec'].str.strip("[]").str.split(", ").apply(pd.Series.value_counts).fillna(0).astype(np.int16))
编辑:
我只是想添加,我假定它将比您当前的方法快,因为它只会创建index_vec
列表中存在的列,而使用范围可能会创建多余的列可能实际上从未出现过的列。另外,当您在该循环中创建列时,您将向数据帧中添加一列x
次。.但是,这里您向df中添加了x
列一次。
但是,如果没有在两个实现之间运行计时器的完整数据,我不能确定...但是希望这样做可以为您加快速度。
编辑: 需要额外的列:
import pandas as pd
import numpy as np
neg_index = -100
pos_index = 2000
df = pd.DataFrame({'index_vec': ["[370, -1, -1]", "[1201, 1201]", "[-2, 676, 676]", "[641, 641]", "[811, 811]"]})
df = df.join(df['index_vec'].str.strip("[]").str.split(", ").apply(pd.Series.value_counts).fillna(0).astype(np.int16))
uninitialized = list(set([str(x) for x in range(neg_index, pos_index)]).difference(df.columns.values.tolist()))
df[uninitialized] = pd.DataFrame([[0]*len(uninitialized)], index=df.index)