Pandas DataFrame:合并具有相同 ID 的行

Pandas DataFrame: Merge rows with same id

我有一个 pandas 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_2q1,q2,q3 被拆分。 (timestampscodecode_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

对于问题 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(所以整行会排在第一位),然后从问题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 内置函数。

比较使用和不使用应用功能的运行时间: 数据集:

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 示例的应用解决方案:

  • 7.21 秒 每个循环 ± 8.56 毫秒(7 次运行的平均值 ± 标准差,每次 1 个循环)

没有通过我的解决方案应用的解决方案:

  • 98.4 ms 每个循环 ± 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(行中没有空单元格):

输入:

结果:

如您所见,两者的结果相同。