由于文本换行创建多行而清理 DataFrame

Cleaning up DataFrame due to text wrapping creating multiple lines

我有一个 DataFrame,我正在处理基于文本换行的拆分。说明已拆分为多行,其中单独列中的关键数据 "Values" 仅出现在说明的第一行。我希望做两件事:

  1. 从额外的换行中合并描述中的信息。
  2. 删除没有"Values"
  3. 的附加行

我一直在尝试遍历行,但收效甚微。这是一些显示问题数据框的示例代码(只是一个例子):

import pandas as pd
a = ["This is", "the first", "line", "second", "line", "third", "line", "(no pattern)", "fourth", "fifth"]
b = [1, "", "", 3, "", 47, "", "", 1, 2]
df = pd.DataFrame()
df['Description'] = a
df['Values'] = b
df.head(10)

我已经尝试了一些东西。现在我只是想让循环确定 "Values" 中是否有任何内容,这是我正在使用的当前简短代码:

for index, row in df.iterrows():
if row.Values != '':
    a = row["Description"]
else:
    b = row["Description"]
    c = a + b
    print(c)
    #print(row["Values"])

经过一整天的努力,我得到了答案!!!看起来确实很啰嗦,如果您有其他答案,请告诉我。这是我的回答:

a_array = np.array([]) 
for index, row in df.iterrows():
    if row.Values != '':
        a = int(index)
    a_array = np.append(a_array, a)
df['a']= a_array
df['Description'] = df.groupby(['a'])['Description'].transform(lambda x: ' '.join(x))
df.replace("", np.nan, inplace=True) # replace blank values with NaN
df.dropna(subset = ['Values']) #Drop rows with NaN in Values

此代码通过遍历行并在值出现在 "Values" 中时识别索引来工作。我将其添加为数据框列 'a',然后按 'a' 的值分组,将所有字符串与 space ' '.

连接起来

然后空白处输入了 NaN 值 (np.nan),我删除了 "Values".

列中所有带有 NaN 的行

这避免了普通 Python 迭代,后者在 Pandas 中很慢。这里的关键是找到一对值列中的数字和描述中的条目;这种配对将使我们能够获得值为空的下方的行,并将它们安全地粘贴回上方的行:

res = (df
       #create a new column
       #to hold rows where Values is not empty
       .assign(desc = np.where(df.Values.ne(""),df.Description,np.nan))
       #change the empty rows to null
       .replace({"":np.nan})
       #fill downwards
       .ffill()
       #ensure sort is False
       #to keep data as is
       .groupby(['Values','desc'],sort=False)
       #join similar rows with white space
       .agg(" ".join)
       #drop the desc index
       #it has served its purpose
       .droplevel('desc')
       .reset_index()
      )

res

  Values    Description
0   1.0     This is the first line
1   3.0     second line
2   47.0    third line (no pattern)
3   1.0     fourth
4   2.0     fifth

首先,建立一个我们可以用来对描述进行分组的唯一索引。由于 Values 列是新有效组开始的指示符,我们可以按非空值块后跟空行进行分组。我们将使用累积和来区分它们,递增每个非空值:

In [2]: grouper = (df.Values != '').cumsum()
In [3]: grouper
0    1
1    1
2    1
3    2
4    2
5    3
6    3
7    3
8    4
9    5
Name: Values, dtype: int64

我们可以在 pandas groupby 操作中使用它,其中操作 returns 每个组中的连接描述和非空值:

In [4]: df.groupby(grouper).apply(
   ...:     lambda x: pd.Series({
   ...:         'Description': ' '.join(x.Description),
   ...:         'Values': x.Values.values[x.Values != 0][0]
   ...:     })
   ...: ).reset_index(drop=True)

               Description  Values
0   This is the first line       1
1              second line       3
2  third line (no pattern)      47
3                   fourth       1
4                    fifth       2