在 pandas/python 的同一数据框中将两列合并为一列
Posted
技术标签:
【中文标题】在 pandas/python 的同一数据框中将两列合并为一列【英文标题】:Merge two columns into one within the same data frame in 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。你的形象并没有真正的帮助。 You should not post code as an image because: 您希望结果是什么样的?End_Station
是否有除NaN
以外的值,如果有,它们如何与Start_Station
值结合?
我提取/描述数据帧结构的更好方法(什么代码)是什么?
【参考方案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()
其中任何一个。以上是关于在 pandas/python 的同一数据框中将两列合并为一列的主要内容,如果未能解决你的问题,请参考以下文章
在 Pandas/Python 中合并两个数据框,保留数据框 1 中的所有列
根据其他列值/ Pandas -Python 在数据框中创建 ID 列