在列上迭代并用提取的字符串替换值[Pandas]

2024-05-14 19:20:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个数据集,看起来是这样的:

  A   B
1 aa  1234
2 ab  3456
3 bc  [1357, 2468]
4 cc  8901
...

我需要遍历B列,并将方括号([])中的所有值替换为这些括号中的四个左数字,因此数据集将如下所示:

  A   B
1 aa  1234
2 ab  3456
3 bc  1357
4 cc  8901
...

我有这个密码:

for item in df['B']:
if len(item) > 4:
    item_v = str(item[1:5])
    df['B'][item] = item_v 
    print(df['B'][item])

但是,如果我检查df的头,它仍然有旧的值:

   > df['B'].head()

   >  A   B
    1 aa  1234
    2 ab  3456
    3 bc  [1357, 2468]
    4 cc  8901
    ...

我做错什么了?


Tags: 数据in密码dfforifab数字
2条回答

在您的代码中,您正在循环遍历数据帧的B列中的项,但是您没有方法索引回原始数据帧。具体来说,这条线:

df['B'][item] = item_v

不做你想做的事。它正在B列中放置一个索引为item的新项。如果你用一个小数据帧来尝试,你可能会在帧的末尾看到一些奇怪的值。当我尝试这个,我得到:

In[36]: df
Out[36]: 
    A     B
0  aa  1234
1  ab  3456
2  bc  1357
3  cc  8901

In[37]: df['B'][item] = item_v

In[38]: df['B']
Out[38]: 
0       1234
1       3456
2       1357
3       8901
8901    8901 <-- ???
Name: B, dtype: object

更糟糕的是,这一行并没有将值插入到您期望的数据帧中。只有在查看df['B']时,才能看到新元素。如果您只查看df,您将看到原始数据帧,而没有额外的项。

在数据帧中设置元素的正确方法是使用.loc[]类似于:

df.loc[item,'B'] = item_v

这仍然不能解决最初的问题,即如何获得正确的索引。原始代码的一个修复方法是为列表中B列中的每个项累积值,然后将其重新分配给B列,如下所示:

newB = []
for item in df['B']:
    if len(item) > 4:
        item_v = str(item[1:5])
    else:
        item_v = item
    newB.append(item_v)
print(newB)
df.loc[:, 'B'] = newB 

但是,对于pandas,也有一些解决方案不需要直接迭代B列中的项

例如,可以使用^{}来替换长度超过4个字符的字符串以及^{}函数来操作文本元素。这艘班轮的任务是:

df.loc[:,'B'] = df['B'].where((df['B'].str.len() <= 4), df['B'].str[1:5])

此语句创建一个序列,其中包含列B中的项(如果该项为4个或更少字符),或者如果该项超过4个字符,则包含列B中该项的切片[1:5]。然后,这个序列被指定替换df中的列B。

最简单和最快的方法是使用Pandasstr.get()函数并为所需的结果创建另一列。

解决方案#1 如果B中的值是整数[1234,3456,[1357, 2468],8901],则第一个解决方案有效

df['C'] = df['B'].str.get(0).astype(float)
df.C.fillna(df['B'], inplace=True)
df['C'] = df.C.astype(int, inplace=True)

输出:

A             B     C
0  aa          1234  1234
1  ab          3456  3456
2  bc  [1357, 2468]  1357
3  cc          8901  8901

然后,如果不需要,可以删除列B。

解决方案#2 如果B中的值是字符串['1234','3456',['1357', '2468'],'8901'],则此解决方案有效

import re
df['digits'] = df['B'].apply(lambda x: re.findall('\d+', str(x)))
df['digits'] = df['digits'].str.get(0)
print(df)

输出:

   A             B    digits
0  aa          1234   1234
1  ab          3456   3456
2  bc  [1357, 2468]   1357
3  cc          8901   8901

同样,如果不需要,可以删除列B。

相关问题 更多 >

    热门问题