在存在 NaN 的情况下将 pandas 列拆分为新列
Split pandas column into new columns in presence of NaN
我有一个 pandas DataFrame 包含一个字符串列,需要拆分成两个单独的列。我从 this 问题中找到的使用 tolist
的答案就像一个魅力,除非我的专栏包含 NaN。下面的摘录描述了难度:
import pandas as pd
import numpy as np
# Example DataFrame
df = pd.DataFrame([[25.0, '34.2/ 18.1', 'one'],
[32.6, '28.6/ 17.9', 'two'],
[12.5, '30.1/ 17.6', 'three']], columns=['A', 'B', 'C'])
df2 = df.copy()
# This method works when all data are present
df['D'] = pd.DataFrame(df['B'].str.split('/').tolist())[1]
# However, when there are NaNs:
df2['B'][0] = np.nan
# This line fails
df2['D'] = pd.DataFrame(df2['B'].str.split('/').tolist())[1]
它给了我一个 KeyError
,因为中间 DataFrame 只有一列,表明去列表和返回列表的麻烦不再完成任何事情:
0
0 NaN
1 [28.6, 17.9]
2 [30.1, 17.6]
我试过先通过 pd.DataFrame(df2['B'].str.split('/').dropna().tolist())
删除 NaN,但后来我丢失了索引...我需要将 NaN 保持在索引 0。我还想过以某种方式复制 NaN创建中间 DataFrame 以强制两列,但我没有运气。
这就是我需要的 df2 数据:
A B C D
0 25.0 NaN one NaN
1 32.6 28.6/ 17.9 two 17.9
2 12.5 30.1/ 17.6 three 17.6
有没有办法不使用列表作为中介来做到这一点?或者以某种方式处理 NaN?
The str.extract
method 允许您提供正则表达式模式。模式中的每个组都作为单独的列返回。 NaN
没有找到匹配时使用:
df2['D'] = df2['B'].str.extract(r'/(.*)')
print(df2)
产量
A B C D
0 25.0 NaN one NaN
1 32.6 28.6/ 17.9 two 17.9
2 12.5 30.1/ 17.6 three 17.6
请注意,如果您希望 D
列被视为浮点数,那么您还需要调用 astype
:
df2['D'] = df2['D'].astype('float')
如果您在拆分后再次使用 str
访问器(而不是使用 tolist()
并制作另一个 DataFrame),则可以继续使用您的方法:
>>> df2['D'] = df2['B'].str.split('/').str[-1]
>>> df2
A B C D
0 25.0 NaN one NaN
1 32.6 28.6/ 17.9 two 17.9
2 12.5 30.1/ 17.6 three 17.6
这个 returns NaN
如果索引不存在,而不是引发错误。
我有一个 pandas DataFrame 包含一个字符串列,需要拆分成两个单独的列。我从 this 问题中找到的使用 tolist
的答案就像一个魅力,除非我的专栏包含 NaN。下面的摘录描述了难度:
import pandas as pd
import numpy as np
# Example DataFrame
df = pd.DataFrame([[25.0, '34.2/ 18.1', 'one'],
[32.6, '28.6/ 17.9', 'two'],
[12.5, '30.1/ 17.6', 'three']], columns=['A', 'B', 'C'])
df2 = df.copy()
# This method works when all data are present
df['D'] = pd.DataFrame(df['B'].str.split('/').tolist())[1]
# However, when there are NaNs:
df2['B'][0] = np.nan
# This line fails
df2['D'] = pd.DataFrame(df2['B'].str.split('/').tolist())[1]
它给了我一个 KeyError
,因为中间 DataFrame 只有一列,表明去列表和返回列表的麻烦不再完成任何事情:
0
0 NaN
1 [28.6, 17.9]
2 [30.1, 17.6]
我试过先通过 pd.DataFrame(df2['B'].str.split('/').dropna().tolist())
删除 NaN,但后来我丢失了索引...我需要将 NaN 保持在索引 0。我还想过以某种方式复制 NaN创建中间 DataFrame 以强制两列,但我没有运气。
这就是我需要的 df2 数据:
A B C D
0 25.0 NaN one NaN
1 32.6 28.6/ 17.9 two 17.9
2 12.5 30.1/ 17.6 three 17.6
有没有办法不使用列表作为中介来做到这一点?或者以某种方式处理 NaN?
The str.extract
method 允许您提供正则表达式模式。模式中的每个组都作为单独的列返回。 NaN
没有找到匹配时使用:
df2['D'] = df2['B'].str.extract(r'/(.*)')
print(df2)
产量
A B C D
0 25.0 NaN one NaN
1 32.6 28.6/ 17.9 two 17.9
2 12.5 30.1/ 17.6 three 17.6
请注意,如果您希望 D
列被视为浮点数,那么您还需要调用 astype
:
df2['D'] = df2['D'].astype('float')
如果您在拆分后再次使用 str
访问器(而不是使用 tolist()
并制作另一个 DataFrame),则可以继续使用您的方法:
>>> df2['D'] = df2['B'].str.split('/').str[-1]
>>> df2
A B C D
0 25.0 NaN one NaN
1 32.6 28.6/ 17.9 two 17.9
2 12.5 30.1/ 17.6 three 17.6
这个 returns NaN
如果索引不存在,而不是引发错误。