我有一个数据帧.第一列有一个数字列表.第二列是第一列数字列表的平均值.我需要创建第三列,以便从第一列的每个元素中减go 平均值.

df = pd.DataFrame({'A':[[4.2,2.3,6.5,2.3],[4.1,5.3,6.5,3.8]]})
df['avg'] = df['A'].apply(lambda p: np.average(p))
df['a_avg' = df['A'].apply(lambda p: (np.array(p)-df['avg']).to_list()) 

预期输出:

df
           A               avg           a_avg
0     [4.2,2.3,6.5,2.3]   3.825        [0.375, -1.525, 2.675, -1.525]
1     [4.1,5.3,6.5,3.8]   4.925        [-0.825, 0.375, 1.575, -1.125]

为了清楚起见,我创建了第二栏.如果有一种方法,我们可以直接从第一列得到第三列,那也是好的.我写的代码有什么问题?

推荐答案

将列表理解与将列表转换为NumPy一起使用,以提高性能:

df['a_avg'] = [(np.round(np.array(p) - np.average(p), 3)).tolist() for p in df['A']]

或者:

df['a_avg'] = df.A.apply(lambda p: (np.round(np.array(p) - np.average(p), 3)).tolist())
   
print (df)
                      A                           a_avg
0  [4.2, 2.3, 6.5, 2.3]  [0.375, -1.525, 2.675, -1.525]
1  [4.1, 5.3, 6.5, 3.8]  [-0.825, 0.375, 1.575, -1.125]

如果每个列表的长度相同,则矢量化解决方案有效:

arr = np.array(df.A.tolist()) 
df['a_avg'] = np.round(arr - np.average(arr), 3).tolist()
   
print (df)
                      A                            a_avg
0  [4.2, 2.3, 6.5, 2.3]  [-0.175, -2.075, 2.125, -2.075]
1  [4.1, 5.3, 6.5, 3.8]   [-0.275, 0.925, 2.125, -0.575]

Testing performance:

df = pd.DataFrame({'A':[[4.2,2.3,6.5,2.3],[4.1,5.3,6.5,3.8]]})

#2k rows
df = pd.concat([df] * 1000, ignore_index=True)


#Timeless solution 
In [36]: %timeit df["a_avg"] = [[round(e - np.average(lst), 3) for e in lst] for lst in df["A"]]
118 ms ± 659 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [37]: %timeit df['a_avg'] = [(np.round(np.array(p) - np.average(p), 3)).tolist() for p in df['A']]
37.1 ms ± 162 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [38]: %timeit df['a_avg'] = df.A.apply(lambda p: (np.round(np.array(p) - np.average(p), 3)).tolist())
37.7 ms ± 446 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [39]: %%timeit
    ...: arr = np.array(df.A.tolist()) 
    ...: df['a_avg'] = np.round(arr - np.average(arr), 3).tolist()
    ...: 
1.36 ms ± 46.3 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

Testing in 20k rows

#20k rows
df = pd.concat([df] * 10000, ignore_index=True)


In [41]: %timeit df["a_avg"] = [[round(e - np.average(lst), 3) for e in lst] for lst in df["A"]]
1.18 s ± 5.82 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [42]: %timeit df['a_avg'] = [(np.round(np.array(p) - np.average(p), 3)).tolist() for p in df['A']]
366 ms ± 1.25 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [43]: %timeit df['a_avg'] = df.A.apply(lambda p: (np.round(np.array(p) - np.average(p), 3)).tolist())
364 ms ± 824 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [44]: %%timeit
    ...: arr = np.array(df.A.tolist()) 
    ...: df['a_avg'] = np.round(arr - np.average(arr), 3).tolist()
    ...: 
    ...: 
13.7 ms ± 111 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Python相关问答推荐

如何推迟对没有公钥的视图/表的反射?

如何在Pandas 中存储二进制数?

根据多列和一些条件创建新列

每个组每第n行就有Pandas

Plotly:如何更改Heatmap中彩色条的勾选文本

如何让pyparparsing匹配1天或2天,但1天和2天失败?

如何使用Selenium访问svg对象内部的元素

是什么导致对Python脚本的jQuery Ajax调用引发500错误?

添加包含中具有任何值的其他列的计数的列

如何调整spaCy token 化器,以便在德国模型中将数字拆分为行末端的点

将jit与numpy linSpace函数一起使用时出错

为什么带有dropna=False的groupby会阻止后续的MultiIndex.dropna()工作?

如何找到满足各组口罩条件的第一行?

如何让程序打印新段落上的每一行?

在Python中管理打开对话框

SQLAlchemy Like ALL ORM analog

如何让这个星型模式在Python中只使用一个for循环?

在vscode上使用Python虚拟环境时((env))

如果满足某些条件,则用另一个数据帧列中的值填充空数据帧或数组

为什么在FastAPI中创建与数据库的连接时需要使用生成器?