在执行排序条件时查找两个列表或数据框之间的交集
Finding an Intersection between two lists or dataframes while enforcing an ordering condition
我有两个列表(来自两个单独的 pandas 数据帧的列),我想找到两个列表的交集,同时保留顺序或根据条件排序。考虑以下示例:
x = ['0 MO', '1 YR', '10 YR', '15 YR', '2 YR', '20 YR', '3 MO', '3 YR',
'30 YR', '4 YR', '5 YR', '6 MO', '7 YR', '9 MO', 'Country']
y = ['Industry', '3 MO', '6 MO', '9 MO', '1 YR', '2 YR', '3 YR',
'4 YR', '5 YR', '7 YR', '10 YR', '15 YR', '20 YR', '30 YR']
answer = set(x).intersection(y)
变量 answer 产生了重叠的列,但顺序没有保留。有没有一种方法可以对解决方案进行排序,使答案产生:
answer = ['3 MO', '6 MO', '9 MO', '1 YR', '2 YR', '3 YR',
'4 YR', '5 YR', '7 YR', '10 YR', '15 YR', '20 YR',
'30 YR']
即首先按月 ("MO") 和整数对相交列表进行排序,然后按年 ("YR") 及其整数排序?
或者,是否有 pandas 方法可以使用重叠列的两个数据帧(保留或陈述顺序)获得相同的结果?
你可以简单地使用列表理解:
[this_name for this_name in x if this_name in y]
和
[this_name for this_name in y if this_name in x]
我不知道你到底想做什么,但我的回答是针对你描述的用例。如果您想使用 pandas,我认为以下代码可以满足您的需求。如果您有更复杂的数据,我认为您可能需要将列类型更改为 timedelta
以获得更大的灵活性。在这种情况下排序有效,因为 MO
按字母顺序排列在 YR
.
之前
import pandas as pd
df1 = pd.DataFrame({'x': ['0 MO', '1 YR', '10 YR', '15 YR', '2 YR', '20 YR', '3 MO', '3 YR',
'30 YR', '4 YR', '5 YR', '6 MO', '7 YR', '9 MO', 'Country']})
df2 = pd.DataFrame({'y': ['Industry', '3 MO', '6 MO', '9 MO', '1 YR', '2 YR', '3 YR',
'4 YR', '5 YR', '7 YR', '10 YR', '15 YR', '20 YR', '30 YR']})
# drop 'non-standard' data
df1["x"] = df1["x"].apply(lambda x: x if x[0].isdigit() else None)
df2["y"] = df2["y"].apply(lambda x: x if x[0].isdigit() else None)
df1.dropna(inplace=True)
df2.dropna(inplace=True)
# make two columns to sort
df1["value"] = df1["x"].apply(lambda x: int(x[:-2]))
df1["unit"] = df1["x"].apply(lambda x: x[-2:])
df2["value"] = df2["y"].apply(lambda x: int(x[:-2]))
df2["unit"] = df2["y"].apply(lambda x: x[-2:])
# sort by unit and value
df1 = df1.sort_values(by=["unit", "value"]).drop("x", axis=1)
df2 = df2.sort_values(by=["unit", "value"]).drop("y", axis=1)
# merge
df = pd.merge(df1, df2, on=["unit", "value"])
df["result"] = df.apply(lambda x: str(x["value"]) + " " + x["unit"], axis=1)
df.drop(["unit", "value"], axis=1, inplace=True)
df
您可以使用 sorted
函数对 answer
进行排序,方法是将自定义函数作为键传递。由于您想首先按它是 MO 还是 YR 排序,然后按整数值排序,您可以拆分白色 space 并按第二部分(MO 或 YR)评估,然后评估第一部分的整数值。
def sorter(x):
s = x.split()
return (s[1],int(s[0]))
out = sorted(set(x).intersection(y), key=sorter)
输出:
['3 MO', '6 MO', '9 MO', '1 YR', '2 YR', '3 YR', '4 YR', '5 YR', '7 YR', '10 YR', '15 YR', '20 YR', '30 YR']
我有两个列表(来自两个单独的 pandas 数据帧的列),我想找到两个列表的交集,同时保留顺序或根据条件排序。考虑以下示例:
x = ['0 MO', '1 YR', '10 YR', '15 YR', '2 YR', '20 YR', '3 MO', '3 YR',
'30 YR', '4 YR', '5 YR', '6 MO', '7 YR', '9 MO', 'Country']
y = ['Industry', '3 MO', '6 MO', '9 MO', '1 YR', '2 YR', '3 YR',
'4 YR', '5 YR', '7 YR', '10 YR', '15 YR', '20 YR', '30 YR']
answer = set(x).intersection(y)
变量 answer 产生了重叠的列,但顺序没有保留。有没有一种方法可以对解决方案进行排序,使答案产生:
answer = ['3 MO', '6 MO', '9 MO', '1 YR', '2 YR', '3 YR',
'4 YR', '5 YR', '7 YR', '10 YR', '15 YR', '20 YR',
'30 YR']
即首先按月 ("MO") 和整数对相交列表进行排序,然后按年 ("YR") 及其整数排序?
或者,是否有 pandas 方法可以使用重叠列的两个数据帧(保留或陈述顺序)获得相同的结果?
你可以简单地使用列表理解:
[this_name for this_name in x if this_name in y]
和
[this_name for this_name in y if this_name in x]
我不知道你到底想做什么,但我的回答是针对你描述的用例。如果您想使用 pandas,我认为以下代码可以满足您的需求。如果您有更复杂的数据,我认为您可能需要将列类型更改为 timedelta
以获得更大的灵活性。在这种情况下排序有效,因为 MO
按字母顺序排列在 YR
.
import pandas as pd
df1 = pd.DataFrame({'x': ['0 MO', '1 YR', '10 YR', '15 YR', '2 YR', '20 YR', '3 MO', '3 YR',
'30 YR', '4 YR', '5 YR', '6 MO', '7 YR', '9 MO', 'Country']})
df2 = pd.DataFrame({'y': ['Industry', '3 MO', '6 MO', '9 MO', '1 YR', '2 YR', '3 YR',
'4 YR', '5 YR', '7 YR', '10 YR', '15 YR', '20 YR', '30 YR']})
# drop 'non-standard' data
df1["x"] = df1["x"].apply(lambda x: x if x[0].isdigit() else None)
df2["y"] = df2["y"].apply(lambda x: x if x[0].isdigit() else None)
df1.dropna(inplace=True)
df2.dropna(inplace=True)
# make two columns to sort
df1["value"] = df1["x"].apply(lambda x: int(x[:-2]))
df1["unit"] = df1["x"].apply(lambda x: x[-2:])
df2["value"] = df2["y"].apply(lambda x: int(x[:-2]))
df2["unit"] = df2["y"].apply(lambda x: x[-2:])
# sort by unit and value
df1 = df1.sort_values(by=["unit", "value"]).drop("x", axis=1)
df2 = df2.sort_values(by=["unit", "value"]).drop("y", axis=1)
# merge
df = pd.merge(df1, df2, on=["unit", "value"])
df["result"] = df.apply(lambda x: str(x["value"]) + " " + x["unit"], axis=1)
df.drop(["unit", "value"], axis=1, inplace=True)
df
您可以使用 sorted
函数对 answer
进行排序,方法是将自定义函数作为键传递。由于您想首先按它是 MO 还是 YR 排序,然后按整数值排序,您可以拆分白色 space 并按第二部分(MO 或 YR)评估,然后评估第一部分的整数值。
def sorter(x):
s = x.split()
return (s[1],int(s[0]))
out = sorted(set(x).intersection(y), key=sorter)
输出:
['3 MO', '6 MO', '9 MO', '1 YR', '2 YR', '3 YR', '4 YR', '5 YR', '7 YR', '10 YR', '15 YR', '20 YR', '30 YR']