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_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
对于问题 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(行中没有空单元格):
输入:
结果:
如您所见,两者的结果相同。
我有一个 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_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 |
对于问题 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(行中没有空单元格):
输入:
结果:
如您所见,两者的结果相同。