Pandas DataFrame:合并具有相同 ID 的行
Posted
技术标签:
【中文标题】Pandas DataFrame:合并具有相同 ID 的行【英文标题】:Pandas DataFrame: Merge rows with same id 【发布时间】:2021-11-02 09:16:37 【问题描述】:我有一个熊猫DataFrame
,具有以下属性,
timestamp | code | code_2 | q1 | q2 | q3 |
---|---|---|---|---|---|
1525815633939 | 1 | 5 | 0.528285138670663 | 0.0 | -10.2012590087440983 |
1525815633979 | 1 | 5 | 0.728820351190643 | 0.0 | -10.1985732939503924 |
1525815633990 | 6 | 5 | 9.7439931640624877 | 10.25547685467354 | |
1525815633990 | 6 | 5 | 0.92935559526222 | ||
1525815634000 | 6 | 5 | 9.7079931640624864 | 10.25475688648455 | |
1525815634000 | 6 | 5 | 0.029623209410135 |
如您所见,有时一个条目会一分为二,尽管它不是双值的。最后两对行对应于相同的timestamps
、相同的code
和相同的code_2
,但q1,q2,q3
被拆分。
(timestamps
、code
和 code_2
构成我的唯一标识符)。
我想要什么,
timestamp | code | code_2 | q1 | q2 | q3 |
---|---|---|---|---|---|
1525815633939 | 1 | 5 | 0.528285138670663 | 0.0 | -10.2012590087440983 |
1525815633979 | 1 | 5 | 0.728820351190643 | 0.0 | -10.1985732939503924 |
1525815633990 | 6 | 5 | 0.92935559526222 | 9.7439931640624877 | 10.25547685467354 |
1525815634000 | 6 | 5 | 0.029623209410135 | 9.7079931640624864 | 10.25475688648455 |
而且我还需要考虑以下情况,我想继续丢弃“完整行”
timestamp | code | code_2 | q1 | q2 | q3 |
---|---|---|---|---|---|
1525815633939 | 1 | 5 | 0.528285138670663 | 0.0 | -10.2012590087440983 |
1525815633979 | 1 | 5 | 0.728820351190643 | 0.0 | -10.1985732939503924 |
1525815633990 | 6 | 5 | 9.7439931640624877 | 10.25547685467354 | |
1525815633990 | 6 | 5 | 0.92935559526222 | ||
1525815634000 | 6 | 5 | 0.984554565478545 | 9.7079931640624864 | 10.25475688648455 |
1525815634000 | 6 | 5 | 0.029623209410135 |
【问题讨论】:
好吧,我会创建一个函数,它只是选择第一个时间戳并遍历所有时间步以找到等效的时间戳,然后在两个时间戳行中添加 q1、q2、q3,如果其中一个有 NaN,否则对最后一种情况不做任何事情? 这确实是一个选择,但我期待更有效的东西。我有加载的数据,这会很慢,你不觉得吗? 还有,我期待这可以通过内置的 pandas 方法来完成。 嗯,我也很喜欢 :),肯定有一个内置函数,如果两个单元格具有相同的元素,它们可以明确地相加,或者如果其中一个是 NaN,则替换它与其他值。但是对于您的最后一种情况,内置函数如何知道要获得哪个值?喜欢:df.groupby('TimeStamp')['q1'].sum()
以及 q2、q3 等
尝试我的解决方案以获得更好的运行时间(另外由于不使用 apply 功能相对较慢)。 ***.com/a/69055997/7836972
【参考方案1】:
我一直在寻找一种不使用“apply”功能的方法,通过使用 pandas 内置函数来获得更好的运行时间。
比较具有和不具有应用功能的运行时: 数据集:
data_temp1 = 'timestamp':np.concatenate([np.arange(0,30000,1)]*2), 'code':[6,6, 5]*20000, 'code_2':[6,6, 5]*20000, 'q1':[0.134555,0.984554565478545, 54]*20000, 'q2':[9.7079931640624864,None, 43]*20000, 'q3':[10.25475688648455,None, 54]*20000
df = pd.DataFrame(data_temp1)
使用类似于@Andrej Kesely 示例的apply 解决方案:
7.21 秒 ± 8.56 毫秒/循环(平均值 ± 标准偏差,7 次运行,每次 1 次循环)我的解决方案不适用的解决方案:
98.4 毫秒 ± 79.2 µs 每个循环(平均值 ± 标准偏差,7 次运行,每次 10 次循环)我的解决方案: (仅当存在时才会填充空单元格。因此,根据您的两种情况都是正确的)。
按空单元格的数量对行进行排序 按下面的行填充每个组中的每一行(没关系,因为先排序) 删除包含空单元格的行columns_to_groupby = ["timestamp", "code"]
# Sort rows of a dataframe in descending order of None counts
df = df.iloc[df.isnull().sum(1).sort_values(ascending=True).index].set_index(columns_to_groupby)
# group by timestamp column, fill the None cells if exists, delete the incomplete rows (from which we filled in the others)
df.groupby(df.index).bfill().dropna()
示例:
示例 1:
输入:
结果:
示例 2(包含没有空单元格的行):
输入:
结果:
如您所见,两者的结果相同。
【讨论】:
只需将 code_2 添加到 columns_to_groupby (我在迷你示例中使用它)【参考方案2】:对于问题1:你可以.groupby
"timestamp"
、"code"
、"code_2"
,然后是 ffill()/bfill() 值,然后删除重复项:
x = (
df.groupby(["timestamp", "code", "code_2"])
.apply(lambda x: x.ffill().bfill())
.drop_duplicates(["timestamp", "code", "code_2"])
)
print(x)
打印:
timestamp code code_2 q1 q2 q3
0 1525815633939 1 5 0.528285138670663 0.0 -10.2012590087440983
1 1525815633979 1 5 0.728820351190643 0.0 -10.1985732939503924
2 1525815633990 6 5 0.92935559526222 9.7439931640624877 10.25547685467354
4 1525815634000 6 5 0.029623209410135 9.7079931640624864 10.25475688648455
对于问题2:你可以.sort_values
一行中有多少NaN
s(所以整行将在第一位)然后从问题1开始操作:
df["tmp"] = df[["q1", "q2", "q3"]].isna().sum(1)
df = df.sort_values(by="tmp").drop(columns="tmp")
x = (
df.groupby(["timestamp", "code", "code_2"])
.apply(lambda x: x.ffill().bfill())
.drop_duplicates(["timestamp", "code", "code_2"])
)
print(x)
打印:
timestamp code code_2 q1 q2 q3
0 1525815633939 1 5 0.528285138670663 0.0 -10.2012590087440983
1 1525815633979 1 5 0.728820351190643 0.0 -10.1985732939503924
4 1525815634000 6 5 0.984554565478545 9.7079931640624864 10.25475688648455
2 1525815633990 6 5 0.92935559526222 9.7439931640624877 10.25547685467354
【讨论】:
太好了,这就是我想要的。 Pandas 的方法!以上是关于Pandas DataFrame:合并具有相同 ID 的行的主要内容,如果未能解决你的问题,请参考以下文章
合并具有来自两个不同列的匹配值的 DataFrame - Pandas [重复]
如何在一个除一列之外的所有列都相同的 Pandas DataFrame 中合并观察结果?