拆分列中的两种类型的字符串
Splitting two types of strings in a column
我在 "1234/123456789/12/123" 和 "1234/X/123456789/12/123" 列中有两种类型的字符串。我想将它分成五列,只要字符串中有“X”,它就会转到第二列,否则第 2 列保持为空。
预期输出
Col1 Col2 Col3 Col4 Col5
1234 123456789 12 123
1234 X 123456789 12 123
想法是首先使用 Series.str.split
for DataFrame, rename
columns and then test second column if not equal X
, then shifting all columns from second one by DataFrame.shift
和 axis=1
:
df = pd.DataFrame({'a':[ "1234/123456789/12/123", "1234/X/123456789/12/123"]})
df1 = df['a'].str.split('/', expand=True).rename(columns = lambda x: f'Col{x+1}')
m = df1['Col2'].ne('X').to_numpy()
df1.iloc[m, 1:] = df1.iloc[m, 1:].shift(axis=1).fillna('')
print (df1)
Col1 Col2 Col3 Col4 Col5
0 1234 123456789 12 123
1 1234 X 123456789 12 123
我的方法是只创建一个二维列表,然后您可以将其作为 DataFrame 加载。假设您的输入字符串属于您描述的两种情况之一:4 列或 5 列,均以“/”作为分隔符。使用 numpy 的 nan 值作为空条目。
#converts one string to a list of column values
def stringToList(rowString):
rowList = rowString.split("/")
if len(rowList)==5:
return(rowList)
if len(rowList)==4:
rowList = [rowList[0]] + [np.nan] + rowList[1::]
return(rowList)
#converts list of strings to pd dataframe
def convertToDataFrame(listOfStrings):
result = []
for s in listOfStrings:
result.append(stringToList(s))
return pd.DataFrame(result)
尚未测试,但请告诉我它是否有效。您可以在 pd.DataFrame 方法中使用 column=
参数设置列名。
如果您愿意,可以使用正则表达式来完成:
示例:
import pandas as pd
import re
# Create sample DataFrame
df = pd.DataFrame({'s': ["1234/123456789/12/123", "1234/X/123456789/12/123"]})
# Build a named regex pattern.
exp = re.compile(r'(?P<col1>\d+)\/(?P<col2>X)?\/?(?P<col3>\d+)\/(?P<col4>\d+)\/(?P<col5>\d+)')
# Extract parts into columns.
df['s'].str.extract(exp).replace(float('nan'), '')
输出:
col1 col2 col3 col4 col5
0 1234 123456789 12 123
1 1234 X 123456789 12 123
注:
在这种情况下使用的正则表达式模式,可以被视为非常自由,或过于严格——取决于具体的用例。然而,正则表达式的一个很好的特性是,一旦定义了预期的输入文本模式,就可以轻松地更新正则表达式模式以适应目的。因此,已编写此特定模式以适合问题中的用例。
我在 "1234/123456789/12/123" 和 "1234/X/123456789/12/123" 列中有两种类型的字符串。我想将它分成五列,只要字符串中有“X”,它就会转到第二列,否则第 2 列保持为空。 预期输出
Col1 Col2 Col3 Col4 Col5
1234 123456789 12 123
1234 X 123456789 12 123
想法是首先使用 Series.str.split
for DataFrame, rename
columns and then test second column if not equal X
, then shifting all columns from second one by DataFrame.shift
和 axis=1
:
df = pd.DataFrame({'a':[ "1234/123456789/12/123", "1234/X/123456789/12/123"]})
df1 = df['a'].str.split('/', expand=True).rename(columns = lambda x: f'Col{x+1}')
m = df1['Col2'].ne('X').to_numpy()
df1.iloc[m, 1:] = df1.iloc[m, 1:].shift(axis=1).fillna('')
print (df1)
Col1 Col2 Col3 Col4 Col5
0 1234 123456789 12 123
1 1234 X 123456789 12 123
我的方法是只创建一个二维列表,然后您可以将其作为 DataFrame 加载。假设您的输入字符串属于您描述的两种情况之一:4 列或 5 列,均以“/”作为分隔符。使用 numpy 的 nan 值作为空条目。
#converts one string to a list of column values
def stringToList(rowString):
rowList = rowString.split("/")
if len(rowList)==5:
return(rowList)
if len(rowList)==4:
rowList = [rowList[0]] + [np.nan] + rowList[1::]
return(rowList)
#converts list of strings to pd dataframe
def convertToDataFrame(listOfStrings):
result = []
for s in listOfStrings:
result.append(stringToList(s))
return pd.DataFrame(result)
尚未测试,但请告诉我它是否有效。您可以在 pd.DataFrame 方法中使用 column=
参数设置列名。
如果您愿意,可以使用正则表达式来完成:
示例:
import pandas as pd
import re
# Create sample DataFrame
df = pd.DataFrame({'s': ["1234/123456789/12/123", "1234/X/123456789/12/123"]})
# Build a named regex pattern.
exp = re.compile(r'(?P<col1>\d+)\/(?P<col2>X)?\/?(?P<col3>\d+)\/(?P<col4>\d+)\/(?P<col5>\d+)')
# Extract parts into columns.
df['s'].str.extract(exp).replace(float('nan'), '')
输出:
col1 col2 col3 col4 col5
0 1234 123456789 12 123
1 1234 X 123456789 12 123
注:
在这种情况下使用的正则表达式模式,可以被视为非常自由,或过于严格——取决于具体的用例。然而,正则表达式的一个很好的特性是,一旦定义了预期的输入文本模式,就可以轻松地更新正则表达式模式以适应目的。因此,已编写此特定模式以适合问题中的用例。