使用不同类型的单个单元阵列清理数据框列

cleaning dataframe columns with single cell arrays of different types

我正在处理一个包含多列的大型数据框。但是,某些列具有数组形式的数据和数组(单值)。我需要转换只有单元格值的数据框列,即没有数组元素样式。我试过以不同的方式展平、挤压,但无法按照我所看到的方式获得输出。 以下代码再现了我目前正在使用的数据格式:

import pandas as pd
a = [[[10]],[[20]],[[30]],[[40]]]
b=[[50],[60],[70],[80]]
c=[90,100,110,120]
df = pd.DataFrame(list(zip(a,b,c)),columns=['a','b','c'])
print(df)

上面的输出是:

        a     b    c
0  [[10]]  [50]   90
1  [[20]]  [60]  100
2  [[30]]  [70]  110
3  [[40]]  [80]  120

但是,我希望获得如下输出:

    a   b    c
0  10  50   90
1  20  60  100
2  30  70  110
3  40  80  120

如果您能提出解决此问题的建议,那将会很有帮助。

实际数据帧的头部如下:

           acoeff         bcoeff  refdiff  ref18
0  [[0.33907555]]  [11.51908656]    0.000  0.001
1  [[0.34024954]]  [11.45693353]    0.001  0.001
2  [[0.34134777]]  [11.40045124]    0.002  0.001
3  [[0.34297324]]  [11.33036004]    0.004  0.001
4  [[0.34373931]]   [11.2991075]    0.005  0.001

下面给出的字典格式的头部:

{'acoeff': {0: '[[0.33907555]]', 1: '[[0.34024954]]', 2: '[[0.34134777]]', 3: '[[0.34297324]]', 4: '[[0.34373931]]'}, 'bcoeff': {0: '[11.51908656]', 1: '[11.45693353]', 2: '[11.40045124]', 3: '[11.33036004]', 4: '[11.2991075]'}, 'refdiff': {0: 0.0, 1: 0.001, 2: 0.002, 3: 0.004, 4: 0.005}, 'ref18': {0: 0.001, 1: 0.001, 2: 0.001, 3: 0.001, 4: 0.001}}

字符串

去掉 [] 并转换为数字:

(df.update(df.select_dtypes(exclude='number')
             .apply(lambda c: pd.to_numeric(c.str.strip('[]'))))
 )
print(df)

真实名单

您可以使用 str 定位器取消嵌套列表:

df['a'].str[0].str[0]

输出:

0    10
1    20
2    30
3    40
Name: a, dtype: int64

要稍微自动化一些,您可以使用递归函数:

def unnest(x):
    from pandas.api.types import is_numeric_dtype
    if is_numeric_dtype(x):
        return x
    else:
        return unnest(x.str[0])

df2 = df.apply(unnest)

使用每个 Series 的第一项来确定嵌套级别的变体:

def unnest(x):
    from pandas.api.types import is_numeric_dtype
    if len(x)>0 and isinstance(x.iloc[0], list):
        return unnest(x.str[0])
    else:
        return x

df2 = df.apply(unnest)

输出:

    a   b    c
0  10  50   90
1  20  60  100
2  30  70  110
3  40  80  120
任意嵌套

如果每个单元格都有任意嵌套,则可以对每个元素使用相同的逻辑:

def unnest(x):
    if isinstance(x, list) and len(x)>0:
        return unnest(x[0])
    else:
        return x
    
df2 = df.applymap(unnest)

也许不是最好的解决方案。但它有效。

def ravel_series(s):
    try:
        return np.concatenate(s).ravel()
    except ValueError:
        return s

df.apply(ravel_series)

你可以试试这个,

代码:

def clean(el):
  if any(isinstance(i, list) for i in el):
    return el[0][0]
  elif isinstance(row, list):
    return el[0]

df['a'] = df.a.apply(clean)
df['b'] = df.b.apply(clean)

print(df)

输出:

    a   b    c
0  10  50   90
1  20  60  100
2  30  70  110
3  40  80  120