如何从熊猫数据框的列值创建新行

时间:2020-06-12 03:54:13

标签: python pandas dataframe

我有如下数据框

输入

Date         Country    Type         Zip_Incl     Zip_Excl
10/4/2020      FR   Regional        57_67_68    
2/1/2020       GB   Regional                      AB_DD
17/3/2021      GB   Regional        BT_TY         TS_TN
18/3/2021      GB   Regional        
19/1/2021     IN    Regional                      68

我需要根据以下条件转换输入:

1)如果Zip_incl不为空,则应将Zip_incl的值传递到Zip_Final

2)如果存在Zip_incl和Zip_Excl值,则应将Zip_incl的值传递到Zip_Final

3)如果Zip incl为空并且存在Zip_Excl的值,则应将Zip_Excl传递给Zip_Final

输出

Date      Country   Type    Zip_Incl     Zip_Excl   Zip_Final
10/4/2020   FR  Regional     57                     57
10/4/2020   FR  Regional     67                     67
10/4/2020   FR  Regional     68                     68
2/1/2020    GB  Regional                 AB         AB
2/1/2020    GB  Regional                 DD         DD
17/3/2021   GB  Regional     BT          TS         BT
17/3/2021   GB  Regional     TY          TN         TY
18/3/2021   GB  Regional            
19/1/2021   IN  Regional                 68         68

这怎么办?

2 个答案:

答案 0 :(得分:1)

对于您而言,我们可以先用bfill然后用axis=1字符串,再用splitexplode

df['Zip_F']=df.filter(like='Zip').bfill(1).iloc[:,0].str.split('_')
df=df.explode('Zip_F')
df
        Date Country      Type  Zip_Incl Zip_Excl Zip_F
0  10/4/2020      FR  Regional  57_67_68      NaN    57
0  10/4/2020      FR  Regional  57_67_68      NaN    67
0  10/4/2020      FR  Regional  57_67_68      NaN    68
1   2/1/2020      GB  Regional       NaN    AB_DD    AB
1   2/1/2020      GB  Regional       NaN    AB_DD    DD
2  17/3/2021      GB  Regional     BT_TY    TS_TN    BT
2  17/3/2021      GB  Regional     BT_TY    TS_TN    TY
3  18/3/2021      GB  Regional       NaN      NaN   NaN
4  19/1/2021      IN  Regional       NaN       68    68

更新

df[['Zip_Incl','Zip_Excl']]=df[['Zip_Incl','Zip_Excl']].mask(df[['Zip_Incl','Zip_Excl']].notnull(),df.Zip_F,axis=0)
df
Out[178]: 
        Date Country      Type Zip_Incl Zip_Excl Zip_F
0  10/4/2020      FR  Regional       57      NaN    57
0  10/4/2020      FR  Regional       67      NaN    67
0  10/4/2020      FR  Regional       68      NaN    68
1   2/1/2020      GB  Regional      NaN       AB    AB
1   2/1/2020      GB  Regional      NaN       DD    DD
2  17/3/2021      GB  Regional       BT       BT    BT
2  17/3/2021      GB  Regional       TY       TY    TY
3  18/3/2021      GB  Regional      NaN      NaN   NaN
4  19/1/2021      IN  Regional      NaN       68    68

答案 1 :(得分:1)

假设dtypes都是字符串,我会考虑以下

   <!--added id to span tag-->
<h3 class="card-title"><span id="title">Main Title</span> <span class="badge badge-primary" id="counts">0</span>
  <span class="float-right">
<a href="" style="color: #c0c6cc;"><i 
class="mdi mdi-trash-can"></i>
</a>
</span>
</h3>
<select class="form-control" id="select" onchange="optionCheck(this);" required>
  <option value="yor1"> Option 1 </option>
    <option value="yor2">
      Option 2</option>
    <option value="yor3">
      Option 3</option>
</select>
import pandas as pd
import numpy as np
df = pd.DataFrame({"Type":["Regional"]*5,
                   "Zip_Incl":["57_67_68", "", "BT_TY", "", ""],
                   "Zip_Excl":["","AB_DD", "TS_TN", "", "68"]})

# this tell us the element that are not ""
(~df[["Zip_Incl", "Zip_Excl"]].eq(""))

以下内容将返回每行中的第一个非空字符串

   Zip_Incl  Zip_Excl
0      True     False
1     False      True
2      True      True
3     False     False
4     False      True

现在有了一些sel = (~df.eq("")).values.argmax(1) 的技巧,我们可以获得您的输出

numpy

更新:如果您的df不够大,并且您正在寻找一种可以解决问题的解决方案

mat = df[["Zip_Incl", "Zip_Excl"]].values
df["Zip_Final"] = mat[np.arange(mat.shape[0]), sel]

在两种情况下,输出均为

def fun(row):
    if row["Zip_Incl"] != "":
        return row["Zip_Incl"]
    elif row["Zip_Excl"] != "":
        return row["Zip_Excl"]
    else:
        return ""

df["Zip_Final"] = df.apply(fun, axis=1)

Update2::我刚刚意识到您想要然后将 Type Zip_Incl Zip_Excl Zip_Final 0 Regional 57_67_68 57_67_68 1 Regional AB_DD AB_DD 2 Regional BT_TY TS_TN BT_TY 3 Regional 4 Regional 68 68 分成不同的行。使用以前的方法之一,您可以添加这些行

Zip_Final
df["Zip_Final"] = df["Zip_Final"].str.split("_")

# you need pandas > 0 .25
df = df.explode("Zip_Final")

print(df)