我有一个用逗号分隔的值的数据框,我使用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宽多少列。
答案 0 :(得分:4)
这是使用<%= link_to "Printable Receipt (PDF)", cabinpdf_path(@forms, format: 'pdf', disposition: "attachment") %>
的一种解决方案。不需要您创建的中间数据框。
$this->db->select('paymenttype.payTypeId,paymenttype.payTypeNameEn,paymenttype.payTypeNameAr,payment.paymentType');
$this->db->from('paymenttype');
$this->db->join('payment' ,'payment.paymentType = paymenttype.payTypeId AND payment.paymentType = paymenttype.payTypeNameEn AND payment.paymentType = paymenttype.payTypeNameAr');
$query = $this->db->get();
//echo $this->db->last_query();
if ($query->num_rows() > 0 )
{
$viewData['payments'] = $query->result();
print_r($viewData);
}
else
{
echo 'No records found !';
}
说明
魔术发生在这一行:
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
答案 1 :(得分:2)
只需使用pd.MultiIndex.from_product
借用jpp的设置
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
答案 2 :(得分:0)
我首先要设置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)
首先,您可以使用.filter
的{{1}}方法通过正则表达式选择列(如here所示):
pandas.DataFrame
然后,您将获得所有唯一的国家和类型,例如:
>>> 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
希望这会有所帮助