Python 根据另一列的特定值将一行中的单词拆分为几行

Python 根据另一列的特定值将一行中的单词拆分为几行,python,pandas,Python,Pandas,我有这个数据帧df: columnId column2 column3 countsOfWord id1 hogedijk klarenbeek 2016 2 id2 hogedijk klaren

我有这个数据帧df

columnId     column2                                                                  column3    countsOfWord
id1          hogedijk klarenbeek                                                       2016        2
id2          hogedijk klarenbeek zuidoost hogedijk klarenbeek zuidoost                 2012        6
id3          zuidoost clouds                                                           2010        2
id4          artzuid zuidoost hogedijk klarenbeek zuidoost clouds hogedijk klarenbeek  2019        8
df['column2'].iloc[1][0:len(df['column2'].iloc[0])//2]
我迫切需要将countsOfWords上面的行(如id2id4拆分为相等的部分),以便这些行的countsOfWords列只包含两个单词,而不改变列ID第3列。我的df数据帧如下所示:

columnId     column2                                                                  column3    countsOfWord
id1          hogedijk klarenbeek                                                       2016        2
id2          hogedijk klarenbeek                                                       2012        2
id2          zuidoost hogedijk                                                         2012        2
id2          klarenbeek zuidoost                                                       2012        2
id3          zuidoost clouds                                                           2010        2
id4          artzuid zuidoost                                                          2019        2
id4          hogedijk klarenbeek                                                       2019        2
id4          zuidoost clouds                                                           2019        2
id4          hogedijk klarenbeek                                                       2019        2
有人能帮我吗

我尝试了这段代码,但它不会自动为countsOfWords以上两次

columnId     column2                                                                  column3    countsOfWord
id1          hogedijk klarenbeek                                                       2016        2
id2          hogedijk klarenbeek zuidoost hogedijk klarenbeek zuidoost                 2012        6
id3          zuidoost clouds                                                           2010        2
id4          artzuid zuidoost hogedijk klarenbeek zuidoost clouds hogedijk klarenbeek  2019        8
df['column2'].iloc[1][0:len(df['column2'].iloc[0])//2]
您可以尝试此操作(使用
str.split()
zip()
然后):

印刷品:

  columnId              column2  column3  countsOfWord
0      id1  hogedijk klarenbeek     2016             2
1      id2  hogedijk klarenbeek     2012             2
1      id2    zuidoost hogedijk     2012             2
1      id2  klarenbeek zuidoost     2012             2
2      id3      zuidoost clouds     2010             2
3      id4     artzuid zuidoost     2019             2
3      id4  hogedijk klarenbeek     2019             2
3      id4      zuidoost clouds     2019             2
3      id4  hogedijk klarenbeek     2019             2

IIUC我们进行
分解
然后
cumcount
将组拆分为子组

s=df.assign(column2=df.column2.str.split(' ')).explode('column2')

s=s.groupby([s.columnId,s.groupby('columnId').cumcount()//2]).\
        agg({'columnId':'first','column2':' '.join,'column3':'first','countsOfWord':'first'})
s=s.assign(countsOfWord=2).reset_index(drop=True)
s
  columnId              column2  column3  countsOfWord
0      id1  hogedijk klarenbeek     2016             2
1      id2  hogedijk klarenbeek     2012             2
2      id2    zuidoost hogedijk     2012             2
3      id2  klarenbeek zuidoost     2012             2
4      id3      zuidoost clouds     2010             2
5      id4     artzuid zuidoost     2019             2
6      id4  hogedijk klarenbeek     2019             2
7      id4      zuidoost clouds     2019             2
8      id4  hogedijk klarenbeek     2019             2
findall
+
explode

df.assign(column2=df.column2.str.replace(' ','-').str.findall("-".join(["[^-]+"] * 2))).explode('column2')
  columnId              column2  column3  countsOfWord
0      id1  hogedijk-klarenbeek     2016             2
1      id2  hogedijk-klarenbeek     2012             6
1      id2    zuidoost-hogedijk     2012             6
1      id2  klarenbeek-zuidoost     2012             6
2      id3      zuidoost-clouds     2010             2
3      id4     artzuid-zuidoost     2019             8
3      id4  hogedijk-klarenbeek     2019             8
3      id4      zuidoost-clouds     2019             8
3      id4  hogedijk-klarenbeek     2019             8

我们可以将您的值拆分为一个列表,然后将它们拆分为两个元素的相等块

然后我们检查元素数
>2
分解的位置,这些行:

splitted = df['column2'].str.split()
lists = splitted.apply(lambda lst: [lst[i::len(lst)//2] for i in range(len(lst)//2)])
df['column2'] = np.where(splitted.str.len().gt(2), lists, df['column2'])

dfn = df.explode('column2')

dfn['column2'] = np.where(
    dfn['column2'].apply(type).eq(list), 
    dfn['column2'].str.join(', '), 
    dfn['column2']
)

dfn['countsOfWord'] = dfn['column2'].str.split().str.len()

我会把它作为一个列表来处理

tb = [['id1', 'hogedijk klarenbeek', 2016],
['id2', 'hogedijk klarenbeek zuidoost hogedijk klarenbeek zuidoost', 2012],
['id3', 'hogedijk klarenbeek', 2010],
['id4', 'artzuid zuidoost hogedijk klarenbeek zuidoost clouds hogedijk klarenbeek', 2019]]

COL_1 = 0
COL_2 = 1
COL_3 = 2
SPACE = ' '
new_tb = []
for line in tb:
    words = line[COL_2].split(SPACE)
    while len(words) != 0:
        new_line = [line[COL_1]]
        new_word_set = words.pop(0)
        new_word_set += SPACE + words.pop(0)
        new_line.append(new_word_set)
        new_line.append(line[COL_3])
        new_tb.append(new_line)
print(pd.DataFrame(new_tb))

这将实现以下目的:

df[“column2”]=df[“column2”].str.split(r)((?:([^\s]+\s+[^\s]+)\s+)
df=df.explode(“column2”).query(“column2!=”)
#如果给定uou,则其字数始终为偶数:
df[“countOfWords”]=2
#否则:
df[“countOfWords”]=df[“column2”].str.count(r“\s”).add(1)
输出:

columnId column2 column3 countOfWords
0 id1 hogedijk klarenbeek 2016 2
1 id2 hogedijk klarenbeek 2012 2
1 id2 Zuidost hogedijk 2012 2
1 id2 klarenbeek zuidoost 2012 2
2 id3 hogedijk klarenbeek 2010 2
3 id4 artzuid Zuidost 2019 2
3 id4 hogedijk klarenbeek 2019 2
3 id4 zuidoost云2019 2
3 id4 hogedijk klarenbeek 2019 2
现在要分解它

columnId     column2                                                                  column3    countsOfWord
id1          hogedijk klarenbeek                                                       2016        2
id2          hogedijk klarenbeek zuidoost hogedijk klarenbeek zuidoost                 2012        6
id3          zuidoost clouds                                                           2010        2
id4          artzuid zuidoost hogedijk klarenbeek zuidoost clouds hogedijk klarenbeek  2019        8
df['column2'].iloc[1][0:len(df['column2'].iloc[0])//2]
这里唯一棘手的部分是正则表达式:
(?:([^\s]+\s+[^\s]+)\s+

\s
表示单个空白

\s+
代表一个或多个空格(为了安全起见)

[^\s]+
表示一个或多个非
空白字符

(?:…)
将冒号后的模式用作分隔符的前面部分


因此,本质上,您可以按以下方式拆分:一个或多个空格,前面是(整个内容)一个或多个非空格字符,后面是一个或多个空格,后面是一个或多个非空格字符。

我不明白为什么第一行代码不起作用。我这样试过:
s=df.assign(['column2']=df['column2']].str.split('').explode('column2')
我认为在处理数据帧时应该避免纯python循环。请参阅本文:stackoverflow.com/a/55557758/10254804为什么说dataframe对象没有属性explode?@JackZakiZakiulFahmiJailani您使用的是什么版本的
pandas
explode()
是在版本
0.25.0
中引入的,我尝试了这一点,但显然在我在@Erfan应用此代码后出现了数据丢失