【问题标题】:Merge two columns into one within the same data frame in pandas/python在 pandas/python 的同一数据框中将两列合并为一列
【发布时间】:2018-11-12 17:28:54
【问题描述】:

我有一个问题要在同一个数据框(start_end)中将两列合并为一列,同时删除空值。我打算将“起始站”和“结束站”合并为“站”,并根据新的“站”列保留“持续时间”。我已经尝试过 pd.merge、pd.concat、pd.append,但我无法解决。

Start_end 的数据帧:

    Duration    End station     Start station
14  1407        NaN             14th & V St NW
19  509         NaN             21st & I St NW
20  638         15th & P St NW.  NaN
27  1532        NaN              Massachusetts Ave & Dupont Circle NW
28  759         NaN              Adams Mill & Columbia Rd NW

预期输出:

    Duration    stations
14  1407        14th & V St NW
19  509         21st & I St NW
20  638         15th & P St NW
27  1532        Massachusetts Ave & Dupont Circle NW
28  759         Adams Mill & Columbia Rd NW

到目前为止我的代码:

#start_end is the dataframe, 'start station', 'end station', 'duration'
start_end = pd.concat([df_start, df_end])

这是我试图做的:

station = pd.merge([start_end['Start station'],start_end['End station']])

【问题讨论】:

  • 数据框作为文本,而不是图像。
  • 在列的上下文中定义“合并”。请提供带有数据、输入和预期输出的minimal reproducible example。你的形象并没有真正的帮助。
  • 您希望结果是什么样的? End_Station 是否有除NaN 以外的值,如果有,它们如何与Start_Station 值结合?
  • 我提取/描述数据帧结构的更好方法(什么代码)是什么?

标签: python pandas dataframe merge append


【解决方案1】:

使用combine_first。将 col1 中的 null 值替换为 col2

df["station"] = df["End station"].combine_first(df["Start station"])
df.drop(["End station", "Start station"], 1, inplace=True)

【讨论】:

    【解决方案2】:
    >>> df
       Duration      End station                         Start station
    0      1407              NaN                        14th & V St NW
    1       509              NaN                        21st & I St NW
    2       638  15th & P St NW.                                   NaN
    3      1532              NaN  Massachusetts Ave & Dupont Circle NW
    4       759              NaN           Adams Mill & Columbia Rd NW
    

    为两列赋予相同的名称

    >>> df.columns = df.columns.str.replace('.*?station', 'station')
    >>> df
       Duration          station                               station
    0      1407              NaN                        14th & V St NW
    1       509              NaN                        21st & I St NW
    2       638  15th & P St NW.                                   NaN
    3      1532              NaN  Massachusetts Ave & Dupont Circle NW
    4       759              NaN           Adams Mill & Columbia Rd NW
    

    堆栈然后解堆栈。

    >>> s = df.stack()
    >>> s
    0  Duration                                    1407
       station                           14th & V St NW
    1  Duration                                     509
       station                           21st & I St NW
    2  Duration                                     638
       station                          15th & P St NW.
    3  Duration                                    1532
       station     Massachusetts Ave & Dupont Circle NW
    4  Duration                                     759
       station              Adams Mill & Columbia Rd NW
    dtype: object
    >>> df = s.unstack()
    >>> df
      Duration                               station
    0     1407                        14th & V St NW
    1      509                        21st & I St NW
    2      638                       15th & P St NW.
    3     1532  Massachusetts Ave & Dupont Circle NW
    4      759           Adams Mill & Columbia Rd NW
    >>> 
    

    这就是我认为的工作原理:

    .stack 创建一个带有 MultiIndex 的系列并为您处理空值。它在列名上对齐第二级,因为列名相同,所以只有一个 - 取消堆叠只会产生一列。

    如果不更改列名,这实际上只是基于索引之间的差异的猜测。

    >>> # without changing column names
    >>> s.index
    MultiIndex(levels=[[0, 1, 2, 3, 4], ['Duration', 'End station', 'Start station']],
               labels=[[0, 0, 1, 1, 2, 2, 3, 3, 4, 4], [0, 2, 0, 2, 0, 1, 0, 2, 0, 2]])
    
    >>> # column names the same
    >>> s.index
    MultiIndex(levels=[[0, 1, 2, 3, 4], ['Duration', 'station']],
               labels=[[0, 0, 1, 1, 2, 2, 3, 3, 4, 4], [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]])
    

    似乎有点棘手,也许有人会评论它。


    替代方案 - 使用 pd.concat.dropna

    >>> stations = pd.concat([df.iloc[:,1],df.iloc[:,2]]).dropna()
    >>> stations.name = 'stations'
    >>> stations
    2                         15th & P St NW.
    0                          14th & V St NW
    1                          21st & I St NW
    3    Massachusetts Ave & Dupont Circle NW
    4             Adams Mill & Columbia Rd NW
    Name: stations, dtype: object
    
    >>> df2 = pd.concat([df['Duration'], stations], axis=1)
    >>> df2
       Duration                              stations
    0      1407                        14th & V St NW
    1       509                        21st & I St NW
    2       638                       15th & P St NW.
    3      1532  Massachusetts Ave & Dupont Circle NW
    4       759           Adams Mill & Columbia Rd NW
    

    【讨论】:

      【解决方案3】:

      使用ffill

      df.iloc[:,2:4]=df.iloc[:,2:4].ffill(1)
      

      【讨论】:

      • 此方法仅适用于“终端站”,缺少“持续时间”。预期的输出是,“开始站”和“结束站”到一列“站”中,并相应地保留“持续时间”。
      【解决方案4】:

      fillna

      如果NaN 是真正的空值

      df.assign(**{
          'Start station': df['Start station'].fillna(df['End station'])})
      
          Duration      End station                         Start station
      14      1407              NaN                        14th & V St NW
      19       509              NaN                        21st & I St NW
      20       638  15th & P St NW.                       15th & P St NW.
      27      1532              NaN  Massachusetts Ave & Dupont Circle NW
      28       759              NaN           Adams Mill & Columbia Rd NW
      

      mask

      如果NaN 是字符串

      df.assign(**{
          'Start station': df['Start station'].mask(
              lambda x: x == 'NaN', df['End station'])})
      
          Duration      End station                         Start station
      14      1407              NaN                        14th & V St NW
      19       509              NaN                        21st & I St NW
      20       638  15th & P St NW.                       15th & P St NW.
      27      1532              NaN  Massachusetts Ave & Dupont Circle NW
      28       759              NaN           Adams Mill & Columbia Rd NW
      

      【讨论】:

      • NaN 是真正的空值。此方法适用于'Start station',将'End station' 值复制到'Start station '。但是,两列不会合并为一列。预期的输出是,'Start station''End station' 到一列 'stations',并相应地保留 'Duration'
      • @BCKN 我很抱歉,但我对评论感到吃惊。这篇文章包含完成任务所需的所有信息。我可能没有以看起来像银盘的方式呈现它,但那是因为我希望你能从我的回答中提取你需要的东西。困扰我的是,你似乎期望我把它放在你想要的盘子上。它可能会提醒您,在 SO 上发布答案的每个人都是志愿者,他们很可能会花时间做其他事情而不是帮助您。如果我误解了你,请告诉我。
      • 抱歉,我想的不够仔细。实际上,我可以重复使用您的建议,newEnd.assign(**{'End station': newEnd['End station'].fillna(newEnd['Start station'])}),并将Start station 复制到End Station。然后.drop()其中任何一个。
      猜你喜欢
      • 2019-10-19
      • 2019-01-08
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 2021-06-21
      • 2017-01-09
      相关资源
      最近更新 更多