同时使用 zip 和百分位数 - Python
Using zip and percentile together - Python
我正在使用一个熊猫数据框,其中我将列表作为单个单元格元素(用于几列)。我想检查一列列表中每个元素的条件,并 select 其他列中的相应列表元素。我知道这可以使用 zip 命令轻松完成,例如:
p = 5 ; q = 6;
DF['Column3'] = [[b for a, b in zip(x, y) if a > p and a <q ] for x, y in zip(DF['Column1'], DF['Column2'])]
但是我不确定如何在这里使用百分位数,即我想使用列表的某个百分位数而不是固定的 p 和 q(比如 50(相当于 p)百分位数到 90 个百分位数(相当于 q))。
因此,对于一列中的每个单元格(每个单元格组成一个列表),它应该计算分位数值并检查另一列中其他列表(来自相应单元格)的相应列表元素。
举例说明问题(假设是DF):
A
B
Column1
Column2
0
3.4
5.7
[2.1, 2.9, 5.2, 6.8]
[2.5,3.4,1.2,5.1]
1
4
1.7
[1.1, 2.5, 5.6, 11.5, 15.6, 21.5]
[12.15,1.58,5.4,1.2,34.2,67.2]
50-Percentile DF['Column1'][0] 为 4.05,90-Percentile 为 6.32。因此,Column1 中的第三个值满足此条件。 Column2中这个值对应的是1.2。因此 Column3 应该有一个 1.2 的输出列表。下一行也有类似的程序(p = 8.55,q = 18.55):
A
B
Column1
Column2
Column3
0
3.4
5.7
[2.1, 2.9, 5.2, 6.8]
[2.5,3.4,1.2,5.1]
[1.2]
1
4
1.7
[1.1, 2.5, 5.6, 11.5, 15.6, 21.5]
[12.15,1.58,5.4,1.2,34.2,67.2]
[1.2,34.2]
您可以使用 numpy.percentile
获取范围内的两个值。然后,跨列使用列表理解(通过传递 axis=1
)。
作为一个班轮,你可以这样做:
df['Column3'] = (df.assign(Column3=df['Column1'].apply(lambda x: np.percentile(x, [50, 90])))
.apply(lambda x: [b for (a,b) in zip(x['Column1'], x['Column2'])
if x['Column3'][0] < a < x['Column3'][1]], axis=1))
将步骤分解为更详细的内容:
df = pd.DataFrame(
{'A' : [3.4,4],
'B' : [5.7, 1.7],
'Column1' : [[2.1, 2.9, 5.2, 6.8], [1.1, 2.5, 5.6, 11.5, 15.6, 21.5]],
'Column2' : [[2.5,3.4,1.2,5.1],[12.15,1.58,5.4,1.2,34.2,67.2]]})
df['Column3'] = df['Column1'].apply(lambda x: np.percentile(x, 50))
df['Column4'] = df['Column1'].apply(lambda x: np.percentile(x, 90))
df['Column5'] = df.apply(lambda x: [b for (a,b) in zip(x['Column1'], x['Column2'])
if x['Column3'] < a < x['Column4']], axis=1)
df
Out[1]:
A B Column1 \
0 3.4 5.7 [2.1, 2.9, 5.2, 6.8]
1 4.0 1.7 [1.1, 2.5, 5.6, 11.5, 15.6, 21.5]
Column2 Column3 Column4 Column5
0 [2.5, 3.4, 1.2, 5.1] 4.05 6.32 [1.2]
1 [12.15, 1.58, 5.4, 1.2, 34.2, 67.2] 8.55 18.55 [1.2, 34.2]
从那里,您可以:
df = df.drop(['Column3', 'Column4'], axis=1)
我正在使用一个熊猫数据框,其中我将列表作为单个单元格元素(用于几列)。我想检查一列列表中每个元素的条件,并 select 其他列中的相应列表元素。我知道这可以使用 zip 命令轻松完成,例如:
p = 5 ; q = 6;
DF['Column3'] = [[b for a, b in zip(x, y) if a > p and a <q ] for x, y in zip(DF['Column1'], DF['Column2'])]
但是我不确定如何在这里使用百分位数,即我想使用列表的某个百分位数而不是固定的 p 和 q(比如 50(相当于 p)百分位数到 90 个百分位数(相当于 q))。
因此,对于一列中的每个单元格(每个单元格组成一个列表),它应该计算分位数值并检查另一列中其他列表(来自相应单元格)的相应列表元素。
举例说明问题(假设是DF):
A | B | Column1 | Column2 | |
---|---|---|---|---|
0 | 3.4 | 5.7 | [2.1, 2.9, 5.2, 6.8] | [2.5,3.4,1.2,5.1] |
1 | 4 | 1.7 | [1.1, 2.5, 5.6, 11.5, 15.6, 21.5] | [12.15,1.58,5.4,1.2,34.2,67.2] |
50-Percentile DF['Column1'][0] 为 4.05,90-Percentile 为 6.32。因此,Column1 中的第三个值满足此条件。 Column2中这个值对应的是1.2。因此 Column3 应该有一个 1.2 的输出列表。下一行也有类似的程序(p = 8.55,q = 18.55):
A | B | Column1 | Column2 | Column3 | |
---|---|---|---|---|---|
0 | 3.4 | 5.7 | [2.1, 2.9, 5.2, 6.8] | [2.5,3.4,1.2,5.1] | [1.2] |
1 | 4 | 1.7 | [1.1, 2.5, 5.6, 11.5, 15.6, 21.5] | [12.15,1.58,5.4,1.2,34.2,67.2] | [1.2,34.2] |
您可以使用 numpy.percentile
获取范围内的两个值。然后,跨列使用列表理解(通过传递 axis=1
)。
作为一个班轮,你可以这样做:
df['Column3'] = (df.assign(Column3=df['Column1'].apply(lambda x: np.percentile(x, [50, 90])))
.apply(lambda x: [b for (a,b) in zip(x['Column1'], x['Column2'])
if x['Column3'][0] < a < x['Column3'][1]], axis=1))
将步骤分解为更详细的内容:
df = pd.DataFrame(
{'A' : [3.4,4],
'B' : [5.7, 1.7],
'Column1' : [[2.1, 2.9, 5.2, 6.8], [1.1, 2.5, 5.6, 11.5, 15.6, 21.5]],
'Column2' : [[2.5,3.4,1.2,5.1],[12.15,1.58,5.4,1.2,34.2,67.2]]})
df['Column3'] = df['Column1'].apply(lambda x: np.percentile(x, 50))
df['Column4'] = df['Column1'].apply(lambda x: np.percentile(x, 90))
df['Column5'] = df.apply(lambda x: [b for (a,b) in zip(x['Column1'], x['Column2'])
if x['Column3'] < a < x['Column4']], axis=1)
df
Out[1]:
A B Column1 \
0 3.4 5.7 [2.1, 2.9, 5.2, 6.8]
1 4.0 1.7 [1.1, 2.5, 5.6, 11.5, 15.6, 21.5]
Column2 Column3 Column4 Column5
0 [2.5, 3.4, 1.2, 5.1] 4.05 6.32 [1.2]
1 [12.15, 1.58, 5.4, 1.2, 34.2, 67.2] 8.55 18.55 [1.2, 34.2]
从那里,您可以:
df = df.drop(['Column3', 'Column4'], axis=1)