繁体   English   中英

如何在 Pandas Dataframe 中将行与 NAN 合并

[英]How can I merge rows with NAN in a Pandas Dataframe

我有以下 Pandas DataFrame:

|Company  | Sales | Location| 
-----------------------------
|American |    NaN|      NaN|
|Express  |    NaN|      NaN|
|Co.      |  1,000|      USA|
|Apple    |  2,000|      USA|
|Microsoft|    NaN|      NaN|
|Corp.    |  1,500|      USA|

如果一个公司的名字太长,它有一行专门适合这个名字。 我想“合并”一个 wat 中的行,如果有 NaN 销售,它将与下面的行合并,直到有销售记录。

这就是我想要 output 的样子!

|Company             | Sales | Location| 
----------------------------------------
|American Express Co.|  1,000|      USA|
|Apple               |  2,000|      USA|
|Microsoft Corp.     |  1,500|      USA|

我试过fillna,但这只会复制销售额,而我真的想合并,所以我可以将整个公司名称保留在公司列中。

谢谢!

这是一种方法

首先要回填这样,公司名称的所有各个部分都具有相同的销售和位置。 然后在销售和位置上使用 groupby,将名称组合在一起。

我们可以使用 sum 作为公司名称,而不是 apply,但需要注意的是,各个部分之间不会有空格,除非在单独命名的部分中有尾随或前导空格。

df[['Sales', 'Location']]=df[['Sales', 'Location']].fillna(method='bfill')
df.groupby(['Sales','Location'])['Company'].apply(' '.join).reset_index() 

或者,为了避免两家公司的销售额和位置相同的情况,我们为每家公司分配一个唯一的 id(其中 location 不为空)并将其用于合并

# assign an index to rows where location is not null, and we use that to combine the splitted company names

df['idx']=df['Location'].notna().cumsum()
df.loc[df['Location'].isna(),'idx']=np.nan

df[['idx', 'Sales', 'Location']]=df[['idx', 'Sales', 'Location']].fillna(method='bfill')
df.groupby(['idx', 'Sales', 'Location'])['Company'].apply(' '.join).reset_index().drop(columns='idx')

Sales   Location    Company
0   1,000   USA     American Express Co.
1   1,500   USA     Microsoft Corp.
2   2,000   USA     Apple

一种解决方案是引入一个标准,该标准定义了哪些行被假定为更多细节,哪些是“终端”。 然后,它可以用于对行进行排名:为属于同一组的所有行分配相同的排名。 最后,排名可用于将行分组在一起。

df["EndOfLine"] = ~df.Location.isna() & ~df.Location.isna()
df["Rank"] = df.EndOfLine.cumsum().shift(1).fillna(0)

df.groupby("Rank").agg(
    {
        "Company": lambda s: " ".join(s),
        "Sales": lambda x: x.tail(1),
        "Location": lambda x: x.tail(1)
    }
)

如何定义定义何时停止( EndOfLine )是最重要和最脆弱的部分,rest 是一个技术性问题。

为了演示排名如何工作,这里有一个更详细的版本:

df["EndOfLine"] = ~df.Location.isna() & ~df.Location.isna()
df["RawRank"] = df.EndOfLine.cumsum()
df["Rank"] = df.EndOfLine.cumsum().shift(1).fillna(0)

产生:

     Company   Sales Location  EndOfLine  RawRank    Rank
0   American     NaN      NaN      False        0     0.0
1    Express     NaN      NaN      False        0     0.0
2        Co.  1000.0      USA       True        1     0.0
3      Apple  2000.0      USA       True        2     1.0
4  Microsoft     NaN      NaN      False        2     2.0
5      Corp.  1500.0      USA       True        3     2.0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM