0

我有一个如下所示的 pandas DF,我正在尝试将不同行中的值计数转换为以下格式:

   COL1    COL2    COL3
    C1      None    None
    C1      C2      None
    C1      C1      None
    C1      C2      C3

    C1  C2  C3
     1   0   0
     1   1   0
     2   0   0
     1   1   1

我在这里找到了这个答案(在 DataFrame 的每一行中计算 Series 中项目的出现次数

这可以满足我的需要,但在我的数据集(400 万行)上非常慢。我试图用 400,000 行来完成它,但它仍然没有以可接受的速度运行。

我相信它是通过大量数据集进行查找的列表,并且 apply 本质上是一个 for 循环。是巨大的循环减慢了这个过程。这里的潜在解决方案基本上提到不要使用 Apply,这会使这里的执行变得乏味,因为我的列表中有 C1、C2...C100 和 10 个垂直列来验证计数。关于我可以在这里尝试什么来提高性能的任何提示?

这是下面的代码:

df_store = df.apply(pd.Series.value_counts, axis=1)[list_lookup].fillna(0)
4

2 回答 2

0

这就是为什么我们通常不使用apply

df.stack().str.get_dummies().sum(level=0).drop('None',1)
Out[157]: 
   C1  C2  C3
0   1   0   0
1   1   1   0
2   2   0   0
3   1   1   1

或与Counter

from  collections import Counter


pd.DataFrame([ Counter(x) for x in df.values]).drop('None',1)
Out[170]: 
   C1   C2   C3
0   1  NaN  NaN
1   1  1.0  NaN
2   2  NaN  NaN
3   1  1.0  1.0
于 2019-06-17T22:13:41.417 回答
0

如果你想要更快的解决方案,你需要使用 numpy. 使用来自 numpy 的 one-hot 编码并将 ndarray 结果分配给数据帧。根据我的%timeit,它比Counter解决方案快 6 倍。缺点是您需要事先知道要编码的值,在您的情况下是C1, C2, C3....C100

encode_val = np.array(['C1', 'C2', 'C3'])
encode_arr = (df.values[...,None] == encode_val).astype(int).sum(1)

Out[237]:
array([[1, 0, 0],
       [1, 1, 0],
       [2, 0, 0],
       [1, 1, 1]])

pd.DataFrame(encode_arr, columns=encode_val)

Out[238]:
   C1  C2  C3
0   1   0   0
1   1   1   0
2   2   0   0
3   1   1   1
于 2019-06-18T00:20:43.540 回答