我的数据框包含以下4个数字列:['ID', 'A', 'B', 'C']
我想过滤数据以获取数据框,其中,对于列ID中的每个唯一值,我得到行不重复,它们对应于列A的最大值和最小值,B,C
下图显示了输入数据帧和所需的输出数据帧。
我还报告了df#2以蓝色突出显示与简单最大/最小搜索不同的行。因为其中一些是重复的,然后应该用第二个/第三个..最大/最小行替换。
例如,df2
的第三行替换为包含B
(63)列中第二个最大值的行,该列是df1
的第三行。同样,df2
的第四行替换为df1
的第四行,因为它包含列B
的第二个最小值(-75)
此外:
列数可以更改,这意味着更大的问题,我可以拥有的列数多于['A']
,['B']
和['C']
ID的行数可以更改
df3的总行数应为UniqueID*Columns*2
目前我只能使用idxmax()
/ idxmin()
然后使用reindex
数据框来获取df2
df1 = pd.DataFrame({'ID': pd.Series([1. ,1. , 1. , 1 , 2 , 2, 2,2,2,2,2]),
'A': pd.Series([100. , -97. , -56. , 69 , 150 , -120, 30,92,35,-41,-75]),
'B': pd.Series([99., -96., 63., -75., 140, -110, 91,-62,76,10,2]),
'C': pd.Series([98., -95., -45., 39., 130, -100,90,-50,70,-17,33])})
max = df1.groupby('ID')['A', 'B','C'].idxmax().as_matrix()
min = df1.groupby('ID')['A', 'B','C'].idxmin().as_matrix()
index = []
for i in range(len(max)):
for j in range(len(max[0])):
index.append(max[i][j])
index.append(min[i][j])
df2 = df1.reindex(index)
我怎样才能获得df3?数据帧很大(> 1M行),所以我不仅需要一个有效的解决方案,而且我还需要一个有效的解决方案。
答案 0 :(得分:3)
有一种快速方法可以只保留唯一的行:df3 = df1.reindex(set(index))
。这将仅保留第一个最大值。现在,您可以删除df1
之后df1 = df1.drop(df3.index)
的第一个最大值的行,并根据需要重复整个过程(例如3次)
import pandas as pd
df1 = pd.DataFrame({'ID': pd.Series([1. ,1. , 1. , 1 , 2 , 2, 2,2,2,2,2]),
'A': pd.Series([100. , -97. , -56. , 69 , 150 , -120, 30,92,35,-41,-75]),
'B': pd.Series([99., -96., 63., -75., 140, -110, 91,-62,76,10,2]),
'C': pd.Series([98., -95., -45., 39., 130, -100,90,-50,70,-17,33])})
def keep_minmax(df1):
df_max = df1.groupby('ID')['A', 'B','C'].idxmax().as_matrix()
df_min = df1.groupby('ID')['A', 'B','C'].idxmin().as_matrix()
index = []
for i in range(len(df_max)):
for j in range(len(df_max[0])):
index.append(df_max[i][j])
index.append(df_min[i][j])
return df1.reindex(set(index))
df = df1.copy()
results = []
for i in range(3):
result = keep_minmax(df)
result['order'] = i + 1
results.append(result)
df = df.drop(result.index)
df3 = pd.concat(results).sort_values(['ID', 'order'])
print(df3)
将输出
A B C ID order
0 100.0 99.0 98.0 1.0 1
1 -97.0 -96.0 -95.0 1.0 1
2 -56.0 63.0 -45.0 1.0 2
3 69.0 -75.0 39.0 1.0 2
4 150.0 140.0 130.0 2.0 1
5 -120.0 -110.0 -100.0 2.0 1
6 30.0 91.0 90.0 2.0 2
7 92.0 -62.0 -50.0 2.0 2
10 -75.0 2.0 33.0 2.0 2
8 35.0 76.0 70.0 2.0 3
9 -41.0 10.0 -17.0 2.0 3
您可以看到ID=1
,没有第三个订单,因为df1中的所有行都已用完,您必须包含重复的行(如示例所示) df3
)。 你真的想要吗?
我问这个问题,因为从你的帖子中我不清楚在模棱两可的情况下该做什么:如果不同的行对应k
'不同列中的最佳值,或者这个k
本身对于不同的列是不同的。例如,您会从df3
生成什么样的df
,为什么?为简单起见,我们只提取最大值:
A B ID
0 2 1 1.0
1 3 2 1.0
2 1 0 1.0
3 0 3 1.0
我的算法(仅查看最大值)将返回
A B ID order
1 3 2 1.0 1
3 0 3 1.0 1
0 2 1 1.0 2
2 1 0 1.0 3
请注意,第2行和第2行的行(2,1)包含在2&n;顺序中,因为它更高。
您是否有任何其他建议如何处理这种含糊之处?
答案 1 :(得分:2)
使用辅助功能:
def filter_min_and_max(x):
y = pd.DataFrame()
for col in x.columns:
if col != "ID":
y[col] = [max(x[col]), min(x[col])]
# for OP's comment
y[col] = [val_1 for val in zip(x[col].nlargest(3).tolist(), x[col].nsmallest(3).tolist()) for val_1 in val]
return y
df1.groupby("ID").apply(lambda x: filter_min_and_max(x)).reset_index().drop(["level_1"], axis=1)