[英]Split pandas dataframe based on column value
给定以下数据:
test_data = pd.DataFrame({
"col": ["wall", "wall", "lamp", "lamp", "desk", "desk", "desk",
"mug", "floor"],
})
我想根据给定列中的特定值(在本例中为col
)创建三个(两个用于边缘情况)数据集。
例如,如果给出col = lamp
的值,我会期望:
df 1
| col |
|:------|
| wall |
| wall |
df 2
| col |
|:------|
| lamp |
| lamp |
df 3
| col |
|:------|
| desk |
| desk |
| desk |
| mug |
| floor |
我尝试过使用以下内容:
match_str = "mug"
match_start, match_end = (
test_data["col"].eq(match_str).loc[lambda x: x].index.min(),
test_data["col"].eq(match_str).loc[lambda x: x].index.max(),
)
df1_filt = pd.Series(test_data.index).lt(match_start)
df2_filt = pd.Series(test_data.index).between(match_start, match_end)
df3_filt = pd.Series(test_data.index).gt(match_end)
df1, df2, df3 = (
test_data.loc[df1_filt],
test_data.loc[df2_filt],
test_data.loc[df3_filt],
)
这似乎可以处理要求 - 它假设col
是有序的,但如果它没有被订购,那么这个操作无论如何都没有任何意义。
这就像itertools.groupby
的行为,对吧? 我们需要对彼此相邻的事物进行分组,并取决于它们是否等于搜索值。 所以在 pandas 中模仿 Python 的 groupby 是 "diff-ne(0)-cumsum" 成语,所以这里我们使用 go:
In [301]: df
Out[301]:
col
0 wall
1 wall
2 lamp
3 lamp
4 desk
5 desk
6 desk
7 mug
8 floor
In [302]: [sub_frame
for _, sub_frame in df.groupby(df.col.eq("lamp").diff().ne(0).cumsum())]
Out[302]:
[ col
0 wall
1 wall,
col
2 lamp
3 lamp,
col
4 desk
5 desk
6 desk
7 mug
8 floor]
它给出了 3 个数据帧的列表:在“灯流”之前、在灯 stream 期间和之后。 这也将尊重边缘情况。
每当您看到自己试图动态地将某些东西拆分为未知数量的变量时,它可能会引发一个危险信号。 我建议在数据集中创建一个组标志,然后使用它来分组或迭代。
import pandas as pd
test_data = pd.DataFrame(
{
"col": ["wall", "wall", "lamp", "lamp", "desk", "desk", "desk", "mug", "floor"],
}
)
test_data['group'] = test_data['col'].eq('mug').diff().ne(0).cumsum()
print(test_data)
Output
col group
0 wall 1
1 wall 1
2 lamp 1
3 lamp 1
4 desk 1
5 desk 1
6 desk 1
7 mug 2
8 floor 3
如果您出于某种原因必须拆分它们,至少使用字典来存储它们,以便您可以处理返回的各种数量的数据帧。
import pandas as pd
test_data = pd.DataFrame(
{
"col": ["wall", "wall", "lamp", "lamp", "desk", "desk", "desk", "mug", "floor"],
}
)
output = {group:data for group,data in test_data.groupby(test_data['col'].eq('mug').diff().ne(0).cumsum())}
print(output[2])
结果
col
7 mug
match_str = 'lamp'
#breaking point
bp = test_data.loc[test_data['col'] == match_str, :].index
#before bp(smaller than bk's head)
b_bp = test_data.index < bp[0]
#after bp(greater than bk's tail)
a_bp = test_data.index >bp[-1]
df_1 = test_data.iloc[b_bp]
df_1
###
col
0 wall
1 wall
df2 = test_data.iloc[bp]
df2
###
col
2 lamp
3 lamp
df3 = test_data.iloc[a_bp]
df3
###
col
4 desk
5 desk
6 desk
7 mug
8 floor
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.