Удаление пробелов из строки на основе условия - PullRequest
1 голос
/ 01 мая 2020

Я ищу помощи в разделении моих данных. Мои данные имеют пробелы в виде тысяч разделителей, но между метками времени также есть пробелы.

Это пример того, как выглядят данные (в настоящее время это 1 столбец):

Date/Time Var1 Var2 Var3 Var4 Var5 Var6
17/04/2020 00:00:00 133 579.20 31 978.90 377 952.81 179 412.41 203 595.20 70 447.40 
17/04/2020 01:00:00 133 583.70 31 980.40 377 963.41 179 412.41 203 595.20 70 448.20

Я бы нужно, чтобы это выглядело так:

Date/Time           Var1      Var2     Var3      Var4      Var5      Var6
17/04/2020 00:00:00 133579.20 31978.90 377952.81 179412.41 203595.20 70447.40 
17/04/2020 01:00:00 133583.70 31980.40 377963.41 179412.41 203595.20 70448.20

Я пытаюсь go обойти это странное и слишком сложное впечатление, как мне кажется. В одном случае я удалил все пробелы и затем разделил даты, которые я сделал:

df.iloc[:,3] = df.iloc[:,3].str.replace('/2020', '/2020 ').str.replace(':00:00', ':00:00 ')

И для того, чтобы затем разбить все числа, я пытался сделать что-то вроде чтения каждого символа в строке и один раз он нашел точку, добавил пробел на 2 строки вперед, но мне не удалось заставить это работать.

for i in range(len(df)):
    for j in df.iloc[i,:]:
        for k in j:
            if k == '.':
               #to be continued

Конечно, есть гораздо более быстрый способ обойти это. Кто-нибудь может мне помочь?

Ответы [ 3 ]

2 голосов
/ 01 мая 2020

Предполагая, что df является вашим текущим фреймом данных, и в нем есть один столбец с именем просто 'D' (если это не 'D', измените его соответствующим образом):

tmplist = df['D'].str.findall(r'(.+?[:.]\S+\s+)').to_list()
tmplist = [ [ e.replace(' ','') if i>0 else e.rstrip() for i, e in enumerate(row) ] for row in tmplist ]
col = ['Date/Time'] + [ 'Var{}'.format(i) for i in range(1,len(tmplist[0])) ]
df = pandas.DataFrame(tmplist, columns=col)

Первая строка преобразует фрейм данных в список списков, разбивая ваши строки по мере необходимости. Используется определенный прием: точка или двоеточие, за которым следуют цифры, являются последними из разделенных пробелами элементов, принадлежащих одному столбцу (двоеточие для метки времени, точка для чисел с плавающей точкой).

Второй удаляет все пробелы из всех столбцов, кроме первого (временные метки), где удаляются только конечные пробелы.

Следующий создает имена столбцов в соответствии с вашим sh.

Последний перестраивает фрейм данных из списка.

1 голос
/ 01 мая 2020

Вы можете попробовать:

out = df[df.columns[0]].str.split(r"\s+")\
    .apply(lambda x: pd.Series([" ".join(x[:2])] + ["{}{}".format(a, b) for a, b in zip(x[2::2], x[3::2])])) \
    .rename(columns={old:new for old, new in enumerate(cols)})

Пояснения :

  1. После выбора единственного столбца с помощью df[df.columns[0]], разделите этот столбец по всем пробелам, используя pandas.Series.str.split. Регулярное выражение простое: \s+: df[df.columns[0]].str.split(r"\s+")
  2. Примените функцию custum к каждой строке, используя apply.

    1. Сначала создайте заново date, объединив два первых элемента с пробелом, преобразовав их в дату и обернув ее в список: [pd.Timestamp(" ".join(x[:2]))]
    2. Объедините все остальные значения 2-by2 , используя zip. Это обсуждение предоставляет более подробную информацию.

    [float("{}{}".format(a, b)) for a, b in zip(x[2::2], x[3::2])]

  3. Преобразуйте этот список в pd.Series результат переноса из шагов 2.1 и 2.2.

Переименуйте столбцы, используя rename. Дикт-понимание позволяет нам выполнить ожидаемый результат: .rename(columns={old:new for old, new in enumerate(cols)})


Полный код + иллюстрация

print(df)
#              Date/Time Var1 Var2 Var3 Var4 Var5 Var6
# 0  17/04/2020 00:00:00 133 579.20 31 978.90 377 9...
# 1  17/04/2020 01:00:00 133 583.70 31 980.40 377 9...

# Step 1
print(df[df.columns[0]].str.split(r"\s+"))
# 0    [17/04/2020, 00:00:00, 133, 579.20, 31, 978.90...
# 1    [17/04/2020, 01:00:00, 133, 583.70, 31, 980.40...
# Name: Date/Time Var1 Var2 Var3 Var4 Var5 Var6, dtype: object

# Step 2.1
print(df[df.columns[0]].str.split(r"\s+")
      .apply(lambda x: [pd.Timestamp(" ".join(x[:2]))]))
# 0    [2020-04-17 00:00:00]
# 1    [2020-04-17 01:00:00]
# Name: Date/Time Var1 Var2 Var3 Var4 Var5 Var6, dtype: object

# Step 2.2
print(df[df.columns[0]].str.split(r"\s+")
      .apply(lambda x: [float("{}{}".format(a, b)) for a, b in zip(x[2::2], x[3::2])]))
# 0    [133579.2, 31978.9, 377952.81, 179412.41, 2035...
# 1    [133583.7, 31980.4, 377963.41, 179412.41, 2035...
# Name: Date/Time Var1 Var2 Var3 Var4 Var5 Var6, dtype: object

# Step 2.3
print(df[df.columns[0]].str.split(r"\s+")
      .apply(lambda x: pd.Series([pd.Timestamp(" ".join(x[:2]))] + [float("{}{}".format(a, b)) for a, b in zip(x[2::2], x[3::2])])))
#                     0         1        2          3          4         5        6
# 0 2020-04-17 00:00:00  133579.2  31978.9  377952.81  179412.41  203595.2  70447.4
# 1 2020-04-17 01:00:00  133583.7  31980.4  377963.41  179412.41  203595.2  70448.2


# Step 3
print(df.columns[0].split(" "))
# ['Date/Time', 'Var1', 'Var2', 'Var3', 'Var4', 'Var5', 'Var6']


out = df[df.columns[0]].str.split(r"\s+")\
    .apply(lambda x: pd.Series([pd.Timestamp(" ".join(x[:2]))] + [float("{}{}".format(a, b)) for a, b in zip(x[2::2], x[3::2])])) \
    .rename(columns={old: new for old, new in enumerate(df.columns[0].split(" "))})
print(out)
#             Date/Time      Var1     Var2       Var3       Var4      Var5     Var6
# 0 2020-04-17 00:00:00  133579.2  31978.9  377952.81  179412.41  203595.2  70447.4
# 1 2020-04-17 01:00:00  133583.7  31980.4  377963.41  179412.41  203595.2  70448.2


print(out.dtypes)
# Date/Time    datetime64[ns]
# Var1                float64
# Var2                float64
# Var3                float64
# Var4                float64
# Var5                float64
# Var6                float64
# dtype: object
0 голосов
/ 01 мая 2020
string = """Date/Time Var1 Var2 Var3 Var4 Var5 Var6
17/04/2020 00:00:00 133 579.20 31 978.90 377 952.81 179 412.41 203 595.20 70 447.40 
17/04/2020 01:00:00 133 583.70 31 980.40 377 963.41 179 412.41 203 595.20 70 448.20"""

head = string.split('\n')[0].split(' ')
values = []
import re
value_regex = re.compile(' \d\d\d\.\d*')
timestamp_regex = re.compile('\d\d:\d\d:\d\d')
for line in string.split('\n')[1:]:
    for value in value_regex.findall(line):
        line = line.replace(value, value.replace(' ','')+',')
    for timestamp in timestamp_regex.findall(line):
        line = line.replace(timestamp, timestamp+',')
    value_cur_line =  [sep[1:] if sep.startswith(' ') else sep for sep in line.split(',') if sep.replace(' ','')!='']
    values.append(value_cur_line)
...