如何基于两组列之间的值组合创建列?

时间:2018-07-01 00:51:18

标签: python pandas dataframe itertools

我有一个用逗号分隔的值的数据框,我使用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宽多少列。

3 个答案:

答案 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

希望这会有所帮助