矢量化 Pandas 个数据帧
vectorizing Pandas dataframes
这是一个数据清理练习,其中数据帧 A 的特定元素应根据通过 B 解码的值设置为 NaN。
我编写了以下代码,其中 3 层嵌套循环将 运行 持续 17 小时:
def Convert(input):
X = np.fromstring(input[1:-1], dtype=np.int, sep=',')
return X
tf = B
# B is a dataframe of descriptors for the A dataframe
# the column 'missing_or_unknown' in B is used to determine the elements of A to be replaced
tf['missing_or_unknown'] = B['missing_or_unknown'].apply(lambda x: Convert(x))
Y = tf['missing_or_unknown'].values
for i in range(0,len(A)):
for j in range(0,85):
for k in range (0,len(Y[j])):
if A.iloc[i,j] == Y[j][k]:
A[i,j] = np.nan
我怀疑瓶颈是长外循环,因为 len(A)
大约是 100 万。所以,这不是使用 Pandas 的最佳方式,我会选择:
for j in range(0,85):
for k in range (0,len(Y[j])):
if A.iloc[:,j] == Y[j][k]:
A.iloc[:,j] = np.nan
然而后者抛出异常:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()
2 个问题:
- 关于性能瓶颈和从矢量化中获益,我的看法是否正确
- 如何正确表达if条件
- Y的计算并不昂贵,它是一个查找数组来确定如何操作A数据帧
如果您想用 np.nan
替换相同位置的 A 的任何条目等于 Y 的条目,您可以使用:
A[A==Y]=np.nan
这是否解决了您的问题?
您的第一个代码可以运行,但速度很慢。
您的第二个代码不起作用,因为 if 语句正在将整列 (Series) A.iloc[:,j]
与一个值进行比较,您可以使用 .any()
,按照建议。
在这里,我比较了我的代码与您第一次尝试使用两个尺寸为 100x85 的数据帧的速度:
import time
A = pd.DataFrame(np.zeros([100,85]))
A.iloc[0,1] = 1
Y = pd.DataFrame(np.ones([100,85]))
start_time = time.time()
A[A==Y]=np.nan
print("--- %s seconds ---" % (time.time() - start_time))
--- 0.030421018600463867 seconds ---
start_time = time.time()
for i in range(0,len(A)):
for j in range(0,85):
for k in range (0,len(Y[j])):
if A.iloc[i,j] == Y[j][k]:
A[i,j] = np.nan
print("--- %s seconds ---" % (time.time() - start_time))
--- 17.413578748703003 seconds ---
这是一个数据清理练习,其中数据帧 A 的特定元素应根据通过 B 解码的值设置为 NaN。
我编写了以下代码,其中 3 层嵌套循环将 运行 持续 17 小时:
def Convert(input):
X = np.fromstring(input[1:-1], dtype=np.int, sep=',')
return X
tf = B
# B is a dataframe of descriptors for the A dataframe
# the column 'missing_or_unknown' in B is used to determine the elements of A to be replaced
tf['missing_or_unknown'] = B['missing_or_unknown'].apply(lambda x: Convert(x))
Y = tf['missing_or_unknown'].values
for i in range(0,len(A)):
for j in range(0,85):
for k in range (0,len(Y[j])):
if A.iloc[i,j] == Y[j][k]:
A[i,j] = np.nan
我怀疑瓶颈是长外循环,因为 len(A)
大约是 100 万。所以,这不是使用 Pandas 的最佳方式,我会选择:
for j in range(0,85):
for k in range (0,len(Y[j])):
if A.iloc[:,j] == Y[j][k]:
A.iloc[:,j] = np.nan
然而后者抛出异常:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()
2 个问题:
- 关于性能瓶颈和从矢量化中获益,我的看法是否正确
- 如何正确表达if条件
- Y的计算并不昂贵,它是一个查找数组来确定如何操作A数据帧
如果您想用 np.nan
替换相同位置的 A 的任何条目等于 Y 的条目,您可以使用:
A[A==Y]=np.nan
这是否解决了您的问题?
您的第一个代码可以运行,但速度很慢。
您的第二个代码不起作用,因为 if 语句正在将整列 (Series) A.iloc[:,j]
与一个值进行比较,您可以使用 .any()
,按照建议。
在这里,我比较了我的代码与您第一次尝试使用两个尺寸为 100x85 的数据帧的速度:
import time
A = pd.DataFrame(np.zeros([100,85]))
A.iloc[0,1] = 1
Y = pd.DataFrame(np.ones([100,85]))
start_time = time.time()
A[A==Y]=np.nan
print("--- %s seconds ---" % (time.time() - start_time))
--- 0.030421018600463867 seconds ---
start_time = time.time()
for i in range(0,len(A)):
for j in range(0,85):
for k in range (0,len(Y[j])):
if A.iloc[i,j] == Y[j][k]:
A[i,j] = np.nan
print("--- %s seconds ---" % (time.time() - start_time))
--- 17.413578748703003 seconds ---