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