如何根据两组列之间的值组合创建列?
Posted
技术标签:
【中文标题】如何根据两组列之间的值组合创建列?【英文标题】:How to create columns based on combinations of values between 2 sets of columns? 【发布时间】:2018-12-09 16:54:45 【问题描述】:我有一个带有逗号分隔值的数据框,我使用 pd.concat 将其拆分出来。
原始df:
org country type
Orange USA, GBR, AUS OWF, PMR, KIQ
Red AUS, RUS, NZL DOG, MOP, LOF
拆分列会给我一个 df,我们称之为 df_wide,
org country_1 country_2 country_3 type_1 type_2 type_3
Orange USA GBR AUS OWF PMR KIQ
Watermelon AUS RUS NZL ODG MOP LOF
从上面的数据框中,我需要以长格式获取单个国家和单个类型的所有可能组合:
org country type
Orange USA OWF
Orange USA PMR
Orange USA KIQ
Orange GBR OWF
Orange GBR PMR
Orange GBR KIQ
..等等
这就是我卡住的地方。我错误地认为我可以使用 pd.wide_to_long 转换数据框,但我认为我的答案围绕使用 itertools。我已经搜索了与此问题相关的论坛,但我仍然没有完全弄清楚。寻找任何建议!原始 df 列中的逗号分隔值也可能是几十个值,因此我不知道我的宽 df 将有多少列宽。
【问题讨论】:
【参考方案1】:这是使用itertools.product
的一种解决方案。它不需要您创建的中间数据框。
from itertools import chain, product
df = pd.DataFrame('org': ['Orange', 'Red'],
'country': ['USA, GBR, AUS', 'AUS, RUS, NZL'],
'type': ['OWF, PMR, KIQ', 'DOG, MOP, LOF'])
split1 = df['country'].str.split(', ')
split2 = df['type'].str.split(', ')
lens = split1.map(len) * split2.map(len)
c_list, t_list = zip(*chain.from_iterable(map(product, split1, split2)))
res = pd.DataFrame('org': np.repeat(df['org'], lens),
'country': c_list,
'type': t_list)
说明
魔法发生在这行:
c_list, t_list = zip(*chain.from_iterable(map(product, split1, split2)))
由内而外的工作:
计算split1
/ split2
中每对项目的笛卡尔积。
将它们链接在一起,形成一个非嵌套的可迭代结果。
解压并压缩到国家和类型。
结果
print(res)
org country type
0 Orange USA OWF
0 Orange USA PMR
0 Orange USA KIQ
0 Orange GBR OWF
0 Orange GBR PMR
0 Orange GBR KIQ
0 Orange AUS OWF
0 Orange AUS PMR
0 Orange AUS KIQ
1 Red AUS DOG
1 Red AUS MOP
1 Red AUS LOF
1 Red RUS DOG
1 Red RUS MOP
1 Red RUS LOF
1 Red NZL DOG
1 Red NZL MOP
1 Red NZL LOF
【讨论】:
【参考方案2】:只需借用 jpp 的设置,使用pd.MultiIndex.from_product
df['country'] = df['country'].str.split(', ')
df['type'] = df['type'].str.split(', ')
s=[pd.MultiIndex.from_product(x).tolist() for x in list(zip(df['country'],df['type']))]
df=pd.DataFrame('org':df.org.repeat(list(map(len,s)))).reset_index(drop=True)
df[['country','type']]=pd.DataFrame(sum(s,[]))
df
org country type
0 Orange USA OWF
1 Orange USA PMR
2 Orange USA KIQ
3 Orange GBR OWF
4 Orange GBR PMR
5 Orange GBR KIQ
6 Orange AUS OWF
7 Orange AUS PMR
8 Orange AUS KIQ
9 Red AUS DOG
10 Red AUS MOP
11 Red AUS LOF
12 Red RUS DOG
13 Red RUS MOP
14 Red RUS LOF
15 Red NZL DOG
16 Red NZL MOP
17 Red NZL LOF
【讨论】:
【参考方案3】:我从设置 df 开始:
import pandas
records = [
"org": "Orange",
"country_1": "USA",
"country_2": "GBR",
"country_3": "AUS",
"type_1": "OWF",
"type_2": "PMR",
"type_3": "KIQ"
,
"org": "Watermelon",
"country_1": "AUS",
"country_2": "RUS",
"country_3": "NZL",
"type_1": "ODG",
"type_2": "MOP",
"type_3": "LOF"
]
df = pandas.DataFrame(records)
首先,您可以使用pandas.DataFrame
的.filter
方法通过正则表达式选择列(如here 所示):
>>> df_countries = df.filter(regex=("country_.*"))
country_1 country_2 country_3
0 USA GBR AUS
1 AUS RUS NZL
>>> df_types = df.filter(regex=("type_.*"))
type_1 type_2 type_3
0 OWF PMR KIQ
1 ODG MOP LOF
然后你可以得到所有独特的国家和类型:
>>> countries_all = df_countries.values.flatten()
array(['USA', 'GBR', 'AUS', 'AUS', 'RUS', 'NZL'], dtype=object)
>>> types_all = df_types.values.flatten()
array(['OWF', 'PMR', 'KIQ', 'ODG', 'MOP', 'LOF'], dtype=object)
然后将它们组合起来就是使用来自itertools
的笛卡尔积:
>>> pandas.DataFrame(list(itertools.product(*[list(countries_all), list(types_all)])))
0 1
0 USA OWF
1 USA PMR
2 USA KIQ
3 USA ODG
4 USA MOP
5 USA LOF
6 GBR OWF
7 GBR PMR
8 GBR KIQ
9 GBR ODG
10 GBR MOP
11 GBR LOF
12 AUS OWF
13 AUS PMR
14 AUS KIQ
15 AUS ODG
16 AUS MOP
17 AUS LOF
18 AUS OWF
19 AUS PMR
20 AUS KIQ
21 AUS ODG
22 AUS MOP
23 AUS LOF
24 RUS OWF
25 RUS PMR
26 RUS KIQ
27 RUS ODG
28 RUS MOP
29 RUS LOF
30 NZL OWF
31 NZL PMR
32 NZL KIQ
33 NZL ODG
34 NZL MOP
35 NZL LOF
现在我知道您可能希望按照 org
执行此操作,在这种情况下,我会在执行过滤器之前对数据帧进行子集化:
orgs = pandas.unique(df["org"])
for org in orgs:
df_org = df[df["org"] == org]
df_countries = df_org.filter(regex=("country_.*"))
df_types = df_org.filter(regex=("type_.*"))
# do rest of the process here and concatenate in the end through `pandas.concat`
希望对你有帮助
【讨论】:
以上是关于如何根据两组列之间的值组合创建列?的主要内容,如果未能解决你的问题,请参考以下文章