解决方案
您可以使用regex + pandas method-chaining 在一行中完成,如下所示。为了更好的可读性,我将其分成多行。有关详细信息,请参阅下面的C 部分。 ?⭐
注意:A 节和 B 节使用 D 节中的数据,这些数据是 OP 之前共享的。后来问题中的数据发生了变化,C 部分给出了这个用例的解决方案。
正则表达式示例:
为了解释regex-pattern 的工作原理,请看以下三个示例:
-
example-1:我在Section-A中使用了这个正则表达式模式。鉴于我们拥有 Section-D 中给出的数据,这将有助于工作。
-
example-2:这是 example-1 中正则表达式的改进版本。我在Section-B 和 C中使用了这种正则表达式模式。
-
example-3:最后,此示例说明了示例 2 中使用的模式如何跳过不需要的文本并仅选择预期的文本括号。
# without alphabetically ordering the columns
(df[COLUMN_NAME] ## access the "data"-column
.fillna('0xUNKN') ## replace nan values with 0xUNKN
.str.findall(pat) ## use regex to extract patterns
.apply(lambda x: dict((k, v) for v, k in x if (int(v)!=0))) ## row-wise create dict to construct final {column: count} structure
.apply(pd.Series) ## use dict to create columns
.fillna(0) ## replace NaN values with 0
)
A.每个操作都有说明
我在这里解释每个操作的作用,最后按字母顺序重新排列列。
正则表达式解释:example-1
在此处查找有关正则表达式 (\d+)x(\w+)\s*,\s*(\d+)x(\w+) 如何从输入文本中提取各种预期部分的详细说明:example-1。
# NOTE: I am using the dataframe that I created in
# the Dummy Data section "below"
df2 = (df.data # access the "data"-column
.str.findall('(\d+)x(\w+)\s*,\s*(\d+)x(\w+)') # use regex to extract patterns
.explode() # explode each rows' list into columns
.apply(lambda x: {x[1]: x[0], x[3]: x[2]}) # row-wise create dict to construct final {column: count} structure
.apply(pd.Series) # expand each cell into columns
.fillna(0) # replace NaN values with 0
)
df2 = df2.reindex(sorted(df2.columns), axis=1) # alphabetically reorder columns
print(df2)
输出:
AAAA BBBB CCCC
0 1 1 0
1 1 2 0
2 1 0 1
B.更通用的解决方案
如果每行有两种以上的类型(例如,AAAA、BBBB、CCCC),则以下解决方案也适用于这种情况。
正则表达式解释:example-2
在此处找到有关正则表达式 (?:\s*(\d+)x(\w+)\s*)+ 如何从输入文本中提取各种预期部分的详细说明:example-2。
代码
import pandas as pd
## Dummy Data
data = [
'1xAAAA,2xBBBB,3xDDDD',
'1xBBBB,1xAAAA,6xEEEE',
'1xAAAA,1xCCCC,3xDDDD',
]
df = pd.DataFrame(data, columns=['data'])
print('\n Input:')
print(df)
## Output:
# data
# 0 1xAAAA,2xBBBB,3xDDDD
# 1 1xBBBB,1xAAAA,6xEEEE
# 2 1xAAAA,1xCCCC,3xDDDD
## Process DataFrame
# define regex pattern
pat = '(?:\s*(\d+)x(\w+)\s*)+' # regex search pattern
# create dataframe in the expected format
df2 = (df.data ## access the "data"-column
.str.findall(pat) ## use regex to extract patterns
.apply(lambda x: dict((k, v) for v, k in x)) ## row-wise create dict to construct final {column: count} structure
.apply(pd.Series) ## use dict to create columns
.fillna(0) ## replace NaN values with 0
)
df2 = df2.reindex(sorted(df2.columns), axis=1) ## alphabetically reorder columns
print('\n Output:')
print(df2)
## Output:
# AAAA BBBB CCCC DDDD EEEE
# 0 1 2 0 3 0
# 1 1 1 0 0 6
# 2 1 0 1 3 0
C. OP 共享数据的具体示例?⭐
这是一个关于 OP 共享的特定样本数据的示例。此特定用例显示数据框中存在 nan 值。作为使用先前建议的解决方案且修改最少的策略,您可以只使用字符串0xUNKN 来replace 那些nan 值,然后过滤不以0 开头的结果。
import pandas as pd
COLUMN_NAME = 'SmVariant'
## Dummy Data
data = [
'1xFBBC', float('nan'),
'2xFBBA', '5xABIA',
'2xFBBC, 1xFBBA',
'1xFBBA', '4xABIA',
'1xFBBA, 1xFBBC',
float('nan'), '1xFBBA',
'3xFBBA, 1xFBBC',
]
df = pd.DataFrame({COLUMN_NAME: data})
print('\n Input:')
print(df)
## Output:
# SmVariant
# 0 1xFBBC
# 1 NaN
# 2 2xFBBA
# 3 5xABIA
# 4 2xFBBC, 1xFBBA
# 5 1xFBBA
# 6 4xABIA
# 7 1xFBBA, 1xFBBC
# 8 NaN
# 9 1xFBBA
# 10 3xFBBA, 1xFBBC
## Process DataFrame
# define regex pattern
pat = '(?:\s*(\d+)x(\w+)\s*)+' # regex search pattern
# create dataframe in the expected format
df2 = (df[COLUMN_NAME] ## access the "data"-column
.fillna('0xUNKN') ## replace nan values with 0xUNKN
.str.findall(pat) ## use regex to extract patterns
.apply(lambda x: dict((k, v) for v, k in x if (int(v)!=0))) ## row-wise create dict to construct final {column: count} structure
.apply(pd.Series) ## use dict to create columns
.fillna(0) ## replace NaN values with 0
)
df2 = df2.reindex(sorted(df2.columns), axis=1) ## alphabetically reorder columns
print('\n Output:')
print(df2)
## Output:
# ABIA FBBA FBBC
# 0 0 0 1
# 1 0 0 0
# 2 0 2 0
# 3 5 0 0
# 4 0 1 2
# 5 0 1 0
# 6 4 0 0
# 7 0 1 1
# 8 0 0 0
# 9 0 1 0
# 10 0 3 1
D.虚拟数据
import pandas as pd
data = {
'1xAAAA,2xBBBB',
'1xBBBB,1xAAAA',
'1xAAAA,1xCCCC',
}
df = pd.DataFrame(data, columns=['data'])
print(df)
## Output:
# data
# 0 1xBBBB,1xAAAA
# 1 1xAAAA,2xBBBB
# 2 1xAAAA,1xCCCC
参考文献
-
Re-ordering columns in pandas dataframe based on column name [duplicate]
-
pandas.DataFrame.explode
-
Expand Cells Containing Lists Into Their Own Variables In Pandas