Python 计算列值满足不同条件的时间百分比
我有一个类似下面的数据框架,只有大约25列和3000行。我需要第二个DF,它显示DF_a中每列中的所有行>=DF_B中的目标的时间百分比 例如,在df_A中,列d02五分之三大于等于0.04(列的长度),因此应在df_B中反映为60% 我知道如何分别进行比较和百分比,但我不知道如何将所有内容放在一起并填充新的DFPython 计算列值满足不同条件的时间百分比,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个类似下面的数据框架,只有大约25列和3000行。我需要第二个DF,它显示DF_a中每列中的所有行>=DF_B中的目标的时间百分比 例如,在df_A中,列d02五分之三大于等于0.04(列的长度),因此应在df_B中反映为60% 我知道如何分别进行比较和百分比,但我不知道如何将所有内容放在一起并填充新的DF df_A d01 d02 d03 0 0.028 0.021 0.028 1 0.051 0.063 0.093
df_A
d01 d02 d03
0 0.028 0.021 0.028
1 0.051 0.063 0.093
2 0.084 0.084 0.084
3 0.061 0.061 0.072
4 0.015 0.015 0.015
目标
df_B
target d01 d02 d03
.02 p p p
.04 p .60 p
.06 p p p
.08 p p p
.15 p p p
.20 p p p
.25 p p p
.30 p p p
方法
- 创建目标列表
- 创建一个字典,该字典将与每个列名、目标对应的百分比列表相关联
- 在目标上循环,对于每个目标,在列上循环以计算百分比并将其放入字典中
- 使用字典和目标列表创建一个
DataFrame
代码
实例的结果 假设您已经(从Louis复制了示例数据): 您可以使用lambda函数来计算百分比
df_B.apply(lambda x: df_A.ge(x.name).sum().div(len(df_A)), axis=1).reset_index()
Out[249]:
target d01 d02 d03
0 0.02 0.8 0.8 0.8
1 0.04 0.6 0.6 0.6
2 0.06 0.4 0.6 0.6
3 0.08 0.2 0.2 0.4
4 0.15 0.0 0.0 0.0
5 0.20 0.0 0.0 0.0
6 0.25 0.0 0.0 0.0
7 0.30 0.0 0.0 0.0
一种方法是使用
numpy
:
a, t, n = df_A.values, df_T.values, len(df_A.index)
res = np.zeros((len(df_T.index), len(df_A.columns)))
for i in range(res.shape[0]):
for j in range(res.shape[1]):
res[i, j] = np.sum(a[:, j] >= t[i]) / n
result = df_T.join(pd.DataFrame(res, columns=df_A.columns))
设置
df_A:
df_T:
结果
target d01 d02 d03
0 0.02 0.8 0.8 0.8
1 0.04 0.6 0.6 0.6
2 0.06 0.4 0.6 0.6
3 0.08 0.2 0.2 0.4
4 0.15 0.0 0.0 0.0
5 0.20 0.0 0.0 0.0
6 0.25 0.0 0.0 0.0
7 0.30 0.0 0.0 0.0
绩效基准测试
可以使用numba
进一步优化numpy
版本
%timeit allen(df_A, target) # 40ms
%timeit louis(df_A, target) # 7.79ms
%timeit jpp(df_A, df_T) # 4.29ms
df_A = pd.concat([df_A]*10)
df_T = pd.concat([df_T]*5)
target = [.02, .04, .06, .08, .15, .20, .25, .30] * 5
def allen(df_A, target):
df_B = pd.DataFrame(index=target, columns=df_A.columns).rename_axis('target',axis=0)
return df_B.apply(lambda x: df_A.ge(x.name).sum().div(len(df_A)), axis=1).reset_index()
def jpp(df_A, df_T):
a, t, n = df_A.values, df_T.values, len(df_A.index)
res = np.zeros((len(df_T.index), len(df_A.columns)))
for i in range(res.shape[0]):
for j in range(res.shape[1]):
res[i, j] = np.sum(a[:, j] >= t[i]) / n
return df_T.join(pd.DataFrame(res, columns=df_A.columns))
def louis(df_A, target):
dic = {key: [] for key in df_A}
for t in target:
for key in dic:
s = 0
for val in df_A[key]:
if val >= t:
s += 1
dic[key].append(s / len(df_A[key]))
return pd.DataFrame(data = dic, index = target)
numpy方法很棒,因为我不必将df转换为dict并返回。谢谢你的解决方案。工作得很好。
a, t, n = df_A.values, df_T.values, len(df_A.index)
res = np.zeros((len(df_T.index), len(df_A.columns)))
for i in range(res.shape[0]):
for j in range(res.shape[1]):
res[i, j] = np.sum(a[:, j] >= t[i]) / n
result = df_T.join(pd.DataFrame(res, columns=df_A.columns))
d01 d02 d03
0 0.028 0.021 0.028
1 0.051 0.063 0.093
2 0.084 0.084 0.084
3 0.061 0.061 0.072
4 0.015 0.015 0.015
target
0 0.02
1 0.04
2 0.06
3 0.08
4 0.15
5 0.20
6 0.25
7 0.30
target d01 d02 d03
0 0.02 0.8 0.8 0.8
1 0.04 0.6 0.6 0.6
2 0.06 0.4 0.6 0.6
3 0.08 0.2 0.2 0.4
4 0.15 0.0 0.0 0.0
5 0.20 0.0 0.0 0.0
6 0.25 0.0 0.0 0.0
7 0.30 0.0 0.0 0.0
%timeit allen(df_A, target) # 40ms
%timeit louis(df_A, target) # 7.79ms
%timeit jpp(df_A, df_T) # 4.29ms
df_A = pd.concat([df_A]*10)
df_T = pd.concat([df_T]*5)
target = [.02, .04, .06, .08, .15, .20, .25, .30] * 5
def allen(df_A, target):
df_B = pd.DataFrame(index=target, columns=df_A.columns).rename_axis('target',axis=0)
return df_B.apply(lambda x: df_A.ge(x.name).sum().div(len(df_A)), axis=1).reset_index()
def jpp(df_A, df_T):
a, t, n = df_A.values, df_T.values, len(df_A.index)
res = np.zeros((len(df_T.index), len(df_A.columns)))
for i in range(res.shape[0]):
for j in range(res.shape[1]):
res[i, j] = np.sum(a[:, j] >= t[i]) / n
return df_T.join(pd.DataFrame(res, columns=df_A.columns))
def louis(df_A, target):
dic = {key: [] for key in df_A}
for t in target:
for key in dic:
s = 0
for val in df_A[key]:
if val >= t:
s += 1
dic[key].append(s / len(df_A[key]))
return pd.DataFrame(data = dic, index = target)