Python Pandas:合并、连接、连接

Python Pandas: merge, join, concat

我有一个数据框,它有一个非唯一的 GEO_ID,每个 GEO_ID 在单独的列(6 个值中的 1 个)中有一个属性 (FTYPE),每个 GEO_ID 都有一个关联的长度类型。

df

    FID GEO_ID  FTYPE   Length_km

0   1400000US06001400100    428 3.291467766

1   1400000US06001400100    460 7.566487367

2   1400000US06001401700    460 0.262190266

3   1400000US06001401700    566 10.49899202

4   1400000US06001403300    428 0.138171389

5   1400000US06001403300    558 0.532913513

如何为 FTYPE 创建 6 个新列(用 1 和 0 表示该行是否具有 FTYPE)和为 FTYPE_Length 创建 6 个新列以使每一行都具有唯一的 GEO_ID ?

我希望我的新数据框具有这样的结构(具有 6 个 FTYPE-s):

FID GEO_ID  FTYPE_428   FTYPE_428_length    FTYPE_460   FTYPE_460_length
0   1400000US06001400100    1   3.291467766 1   7.566487367

到目前为止,我尝试过的是做这样的事情:

import pandas as pd
fname = "filename.csv"
df = pd.read_csv(fname)
nhd = [334, 336, 420, 428, 460, 558, 556]
df1 = df.loc[df['FTYPE']==nhd[0]]
df2 = df.loc[df['FTYPE']==nhd[1]]
df3 = df.loc[df['FTYPE']==nhd[2]]
df4 = df.loc[df['FTYPE']==nhd[3]]
df5 = df.loc[df['FTYPE']==nhd[4]]
df6 = df.loc[df['FTYPE']==nhd[5]]
df7 = df.loc[df['FTYPE']==nhd[6]]
df12 = df1.merge(df2, how='left', left_on='GEO_ID', right_on='GEO_ID')
df23 = df12.merge(df3,how='left', left_on='GEO_ID', right_on='GEO_ID')
df34 = df23.merge(df4,how='left', left_on='GEO_ID', right_on='GEO_ID')
df45 = df34.merge(df5,how='left', left_on='GEO_ID', right_on='GEO_ID')
df56 = df45.merge(df6,how='left', left_on='GEO_ID', right_on='GEO_ID')
df67 = df56.merge(df7,how='left', left_on='GEO_ID', right_on='GEO_ID')
cols = [0,4,7,10,13,16,19]
df67.drop(df67.columns[cols],axis=1,inplace=True)
df67.columns =['GEO_ID','334','len_334','336','len_336','420','len_420','428','len_428','460','len_460','558','len_558','566','len_566']

但这种方法存在问题,因为它将行减少为具有前两个 FTYPE 的行。有没有办法一次合并多个列?

编写一个 for 循环并遍历每一行并使用条件填充值可能更容易,如下所示:

nhd = [334, 336, 420, 428, 460, 558, 556]
for x in nhd:
    df[str(x)] = None
    df["length_"+str(x)] = None
df.head()
for geoid in df["GEO_ID"]:
    #print geoid
    for x in nhd:
        df.ix[(df['FTYPE']==x) & (df['GEO_ID'] == geoid)][str(nhd)] = 1

但这需要太多时间,而且 Pandas 中可能只有一个班轮可以做同样的事情。

如有任何帮助,我们将不胜感激!

谢谢, 所罗门

我不太明白你的 _length 列的意义:它们似乎具有与匹配值是否为 null 相同的信息,这使它们变得多余。不过,它们很容易创建。

如果我们坚持的话,我们可以把它塞进一行,但有什么意义呢?这是 SO,而不是 codegolf。所以我可能会做类似的事情:

df = df.pivot(index="GEO_ID", columns="FTYPE", values="Length_km")
df.columns = "FTYPE_" + df.columns.astype(str)

has_value = df.notnull().astype(int)
has_value.columns += '_length'

final = pd.concat([df, has_value], axis=1).sort_index(axis='columns')

这给了我(使用你的输入数据,它只有 5 个不同的 FTYPE):

In [49]: final
Out[49]: 
                      FTYPE_334  FTYPE_334_length  FTYPE_428  \
GEO_ID                                                         
1400000US06001400100        NaN                 0   3.291468   
1400000US06001401700        NaN                 0        NaN   
1400000US06001403300        NaN                 0   0.138171   
1400000US06001403400    0.04308                 1        NaN   

                      FTYPE_428_length  FTYPE_460  FTYPE_460_length  \
GEO_ID                                                                
1400000US06001400100                 1   7.566487                 1   
1400000US06001401700                 0   0.262190                 1   
1400000US06001403300                 1        NaN                 0   
1400000US06001403400                 0        NaN                 0   

                      FTYPE_558  FTYPE_558_length  FTYPE_566  FTYPE_566_length  
GEO_ID                                                                          
1400000US06001400100        NaN                 0        NaN                 0  
1400000US06001401700        NaN                 0  10.498992                 1  
1400000US06001403300   0.532914                 1   1.518864                 1  
1400000US06001403400        NaN                 0        NaN                 0