提问人:Stan 提问时间:10/15/2023 更新时间:10/16/2023 访问量:86
Pandas Column 使用 Conditional 拆分一行并创建一个单独的 Column
Pandas Column Split a row with Conditional and create a separate Column
问:
似乎这个问题并不难,但不知何故我无法让它工作。我的问题如下。我有一个数据帧,如下所示:
dfin
A B C
a 1 198q24
a 2 128q6
a 6 1456
b 7 67q22
b 1 56
c 3 451q2
d 11 1q789
所以现在我想做的是如下,每当脚本遇到“q”时,它都会拆分值并创建一个单独的列,其值从“q”开始。“q”之前的部分将保留在原始部分(或者可以装箱一个新列)。所以我想要的输出应该如下:
dfout
A B C D
a 1 198 q24
a 2 128 q6
a 6 1456
b 7 67 q22
b 1 56
c 3 451 q2
d 11 1 q789
所以我到目前为止尝试的如下:
dfout = dfin.replace('\q\d*', '', regex=True)
它创建了一个没有 q 的列,但我无法创建 D 列并且无法按预期工作。
任何帮助/想法都会有所帮助并受到赞赏。
答:
1赞
J_H
10/15/2023
#1
import pandas as pd
def get_input() -> pd.DataFrame:
csv_text = """
a 1 198q24
a 2 128q6
a 6 1456
b 7 67q22
b 1 56
c 3 451q2
d 11 1q789
""".strip()
return pd.DataFrame(map(str.split, csv_text.splitlines()), columns=["a", "b", "c"])
def split_on_q(df_in: pd.DataFrame) -> pd.DataFrame:
df = df_in.c.str.split("q", expand=True)
df_out = df_in.copy()
df_out["c"] = df[0]
df_out["d"] = _prepend_q(df[1])
return df_out
def _prepend_q(series: pd.Series) -> pd.Series:
return series.apply(lambda s: None if s is None else f"q{s}")
if __name__ == "__main__":
print(split_on_q(get_input()))
输出:
a b c d
0 a 1 198 q24
1 a 2 128 q6
2 a 6 1456 None
3 b 7 67 q22
4 b 1 56 None
5 c 3 451 q2
6 d 11 1 q789
1赞
Suraj Shourie
10/15/2023
#2
有多种方法可以做到这一点,但一种方法是在拆分“q”上的列后使用:pd.concat
# temp dataframe
df2 = pd.DataFrame(df['C'].str.split('q').to_list(), columns=['C','D'])
# append to original
df = pd.concat([df.drop(columns=['C']), df2], axis=1)
print(df)
打印:
A B C D
0 a 1 198 24
1 a 2 128 6
2 a 6 1456 None
3 b 7 67 22
4 b 1 56 None
5 c 3 451 2
6 d 11 1 789
评论
0赞
user19077881
10/16/2023
根据 OP 预期输出,列 'D' 在数字前应有 q。此外,应为空字符串,而不是 。None
1赞
Panda Kim
10/15/2023
#3
法典
用str.extract
df.assign(D=df['C'].str.extract(r'(q\d*)'))
输出:
A B C D
0 a 1 198q24 q24
1 a 2 128q6 q6
2 a 6 1456 NaN
3 b 7 67q22 q22
4 b 1 56 NaN
5 c 3 451q2 q2
6 d 11 1q789 q789
我意识到我忽略了将 C 列从 @user19077881 更改的必要性。然后使用以下代码
df[['C', 'D']] = df['C'].str.extract(r'(\d+)(q\d+)*')
输出:
A B C D
0 a 1 198 q24
1 a 2 128 q6
2 a 6 1456 NaN
3 b 7 67 q22
4 b 1 56 NaN
5 c 3 451 q2
6 d 11 1 q789
如果不想就地到原始 DF,请使用以下代码:
df[['A', 'B']].join(df['C'].str.extract(r'(?P<C>\d+)(?P<D>q\d+)*'))
示例代码
import pandas as pd
data1 = {'A': ['a', 'a', 'a', 'b', 'b', 'c', 'd'],
'B': [1, 2, 6, 7, 1, 3, 11],
'C': ['198q24', '128q6', '1456', '67q22', '56', '451q2', '1q789']}
df = pd.DataFrame(data1)
评论
0赞
user19077881
10/16/2023
为了产生OP的预期输出,还需要将其应用于str.extract(r'(\d+)q?')
df['C']
0赞
Panda Kim
10/16/2023
@user19077881 您的建议与提问者期望的输出完全不同。最好在提出建议之前运行代码。
0赞
user19077881
10/16/2023
我要指出的是,您保留了原始的列 C,而 OP 只想要 q 之前的数字
0赞
Panda Kim
10/16/2023
@user19077881我误解了你说的话。我道歉。我已经更正了我的答案。
评论