如何将字符串的一部分提取到另一列中

4

我有一个包含如下数据的列:

虚拟数据:

df = pd.DataFrame(["Lyreco A-Type small 2i",
"Lyreco C-Type small 4i",
"Lyreco N-Part medium", 
"Lyreco AKG MT 4i small",
"Lyreco AKG/ N-Type medium 4i",
"Lyreco C-Type medium 2i",
"Lyreco C-Type/ SNU medium 2i",
"Lyreco K-part small 4i",
"Lyreco K-Part medium", 
"Lyreco SNU small 2i",
"Lyreco C-Part large 2i",
"Lyreco N-Type large 4i"])

我想创建一个额外的列,它可以剥离数据并在每一行中给出所需的字符串部分(见下文)。 提取的列应该长成这样

Column_1                      Column_2
Lyreco A-Type small 2i         A-Type
Lyreco C-Type small 4i         C-Type
Lyreco N-Part medium           N-Part
Lyreco STU MT 4i small         STU MT
Lyreco AKG/ N-Type medium 4i   AKG/ N-Type
Lyreco C-Type medium 2i        C-Type
Lyreco C-Type/ SNU medium 2i   C-Type/ SNU
Lyreco K-part small 4i         K-part
Lyreco K-Part medium           K-Part
Lyreco SNU small 2i            SNU
Lyreco C-Part large 2i         C-Part
Lyreco N-Type large 4i         N-Type

我该如何从第一列中提取第二列?

你能解释一下什么是“字符串的中心部分”吗? - alec_djinn
@alec_djinn 提取的字符串应该看起来像列2。对于“中心部分”的示例是第2列。 - ar_mm18
3个回答

3
您可能会发现以下逻辑可适用于您的数据:
df["Column_2"] = df["Column_1"].str.extract(r'\w+ (\S+(?: \S+)*) \b(?:small|medium|large)\b')

以上模式匹配从第二项开始,直到达到“small”、“medium”或“large”关键字。这是一个有效的正则表达式 demo

1
非常感谢,@Tim。它在虚拟数据上运行良好。我将尝试根据我拥有的原始数据重构代码。 - ar_mm18
我有几行类似于“Lyreco STU / C-Type medium 2i”的数据,但这些行被提取为NaN。你能帮我解决这个问题吗? - ar_mm18
1
请查看更新后的答案。 - Tim Biegeleisen
你能否给我发送一个关于如何编写提取语句的链接或文档? - ar_mm18

2

看你发布的例子,只需分割列值并返回“中间”项即可。您可以编写一个简单的函数来封装逻辑并将其应用于数据帧。

from math import floor

df = pd.DataFrame(
    {'Columns_1':
     ["Lyreco A-Type small 2i",
      "Lyreco C-Type small 4i",
      "Lyreco N-Part medium", 
      "Lyreco AKG MT 4i small",
      "Lyreco AKG/ N-Type medium 4i",
      "Lyreco C-Type medium 2i",
      "Lyreco C-Type/ SNU medium 2i",
      "Lyreco K-part small 4i",
      "Lyreco K-Part medium", 
      "Lyreco SNU small 2i",
      "Lyreco C-Part large 2i",
      "Lyreco N-Type large 4i"
     ]
    }
)


def f(row):
    blocks = row['Columns_1'].split()
    mid_index = 1 if len(blocks) <= 4 else floor(len(blocks)/2)
    return ' '.join(blocks[1:mid_index+1])

df['Columns_2'] = df.apply(f, axis=1)

print(df)

输出:

                       Columns_1    Columns_2
0         Lyreco A-Type small 2i       A-Type
1         Lyreco C-Type small 4i       C-Type
2           Lyreco N-Part medium       N-Part
3         Lyreco AKG MT 4i small       AKG MT
4   Lyreco AKG/ N-Type medium 4i  AKG/ N-Type
5        Lyreco C-Type medium 2i       C-Type
6   Lyreco C-Type/ SNU medium 2i  C-Type/ SNU
7         Lyreco K-part small 4i       K-part
8           Lyreco K-Part medium       K-Part
9            Lyreco SNU small 2i          SNU
10        Lyreco C-Part large 2i       C-Part
11        Lyreco N-Type large 4i       N-Type

根据您的代码,第2列中缺少一些数据。 另外,请检查问题中更新的虚拟数据。 如果您发现任何线索,请告诉我 :) - ar_mm18
1
@ar_mm18 已经相应地进行了修正。这就是为什么重要的原因是:1)非常好地描述问题,2)包括一个涵盖您在实际数据中可能遇到的所有情况的示例。 - alec_djinn
再次感谢,下次发布问题时我会牢记这点。在您的解决方案的第三列中,AKG MT应该是答案。但它被跳过了。我无法将其包含在else语句中。 - ar_mm18
1
@ar_mm18 现在怎么样? - alec_djinn

0
df.columns = ['column_1']

df["column_2"] = [col.split(" ")[1] for col in df.column_1]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接