从数据帧内的单个值列表中检索值,数据帧内也有空列表

2024-06-07 07:03:22 发布

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

有点冗长的标题,但我有一个大的数据框,它有单值或无值的列表

import pandas as pd

data = {'Name': ['BN #1', 'HHC', 'A comp', 'B comp', BN #2', 'HHC', 'A comp', 'B comp'],
        'SysNum': ['["1"]', [], [], [], '["2"]', [], [], []]
            }

df = pd.DataFrame(data)

result =

    Name    SysNum
0   BN #1   ['1']
1   HHC     []
2   A comp  []
3   B comp  []
4   BN #2   ['2']
5   HHC     []
6   A comp  []
7   B comp  []

这是较大数据帧的一小部分,其余的4个选项相同,但BN#每次增加1。有没有办法创建一个新列,从列表中提取“1”并将其转换为整数?我试过几种不同的方法,但都没有成功。最后的目标是有一列整数,这样我就可以搜索最大值


Tags: 数据nameimport标题列表data整数pd
3条回答

因为您的一些数据是一个列表[],而其中一些是一个列表的字符串'[]',所以您需要将所有数据转换为字符串,使用literal_eval将所有数据转换为列表,然后分解-假设每个列表中只有一个int

import pandas as pd
from ast import literal_eval

data = {'Name': ['BN #1', 'HHC', 'A comp', 'B comp', 'BN #2', 'HHC', 'A comp', 'B comp'],
        'SysNum': ['["1"]', [], [], [], '["2"]', [], [], []]
            }

df = pd.DataFrame(data)
df['SysNum'] = df['SysNum'].astype(str).apply(literal_eval).explode().astype(float)

     Name SysNum
0   BN #1    1.0
1     HHC    NaN
2  A comp    NaN
3  B comp    NaN
4   BN #2    2.0
5     HHC    NaN
6  A comp    NaN
7  B comp    NaN

前两个答案很好地描述了解决这个问题的方法

我的解决方案只是在需要时增加一些性能

import numpy as np
df['result'] = 0
df.result = np.where(
    len(df.SysNum)>0,
    df.SysNum.str.strip('"[]'),
    0
)

试验

import pandas as pd
import time
data = {'Name': ['BN #1', 'HHC', 'A comp', 'B comp', 'BN #2', 'HHC', 'A comp', 'B comp']*100000,
        'SysNum': ['["1"]', [], [], [], '["2"]', [], [], []]*100000
        }

df = pd.DataFrame(data)
start = time.time()
import numpy as np
df['result'] = 0
df.result = np.where(
    len(df.SysNum)>0,
    df.SysNum.str.strip('"[]'),
    0
)
print(time.time() - start)
# SeaBean
from ast import literal_eval
start = time.time()
df['res'] = df['SysNum'].astype(str).apply(literal_eval).explode().astype(float)
print(time.time() - start)
# It_is_Chris
start = time.time()
df['res1'] = df['SysNum'].astype('str').str.strip(r'\'"[]').map(lambda x: pd.to_numeric(x, errors='coerce')).ffill(downcast='infer')
print(time.time() - start)

在我的Macbook Air M1上给出(我希望这个结果与Arm无关,因为np.where通常是最快的解决方案):

0.3059520721435547
2.994331121444702
4.511949062347412

由于您的最终目标是从字符串列表中提取每个数字并将其转换为整数,而最终目标是只包含一列整数,因此您可以按如下方式执行:

df['SysNum'] = df['SysNum'].astype('str').str.strip(r'\'"[]').map(lambda x: pd.to_numeric(x, errors='coerce')).ffill(downcast='infer')

这里,我们将列更改为字符串类型,然后使用^{}删除"'[]的所有字符。然后,利用^{}将单个数字从字符串类型转换为整数类型。最后,我们使用带有^{}的空列表将这些转换后的整数转发到其他位置

结果:

print(df)

     Name  SysNum
0   BN #1       1
1     HHC       1
2  A comp       1
3  B comp       1
4   BN #2       2
5     HHC       2
6  A comp       2
7  B comp       2

相关问题 更多 >