根据条件从字符串中删除空格
Removing whitespaces from a string based on a condition
我正在寻求拆分数据方面的帮助。我的数据有千位分隔符的空格,但我的时间戳之间也有空格。
这是数据的示例(当前为 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
我认为我正在尝试以一种奇怪且过于复杂的方式解决这个问题。在一个例子中,我删除了所有空格,然后拆分我所做的日期:
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
肯定有更快捷的方法来解决这个问题。谁能帮帮我?
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)
假设 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)
第一行将数据框转换为列表列表,根据需要拆分字符串。使用了一个特定的技巧:点或冒号后跟数字是属于一列的最后一个 space 分隔项(冒号表示时间戳,点表示浮点数)。
第二个从除第一个(时间戳)之外的所有列中删除所有 spaces,它只删除尾随的 spaces。
下一篇根据您的意愿创建列名。
最后一个从列表中重建数据帧。
你可以试试:
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)})
解释:
- 使用
df[df.columns[0]]
选择唯一的列后,使用 pandas.Series.str.split
根据所有 space 拆分此列。正则表达式很简单 \s+
: df[df.columns[0]].str.split(r"\s+")
- 使用
apply
在每行上应用自定义函数。
- 首先通过将前 2 个元素与 space 合并来重新创建日期,转换为日期并将其包装在列表中:
[pd.Timestamp(" ".join(x[:2]))]
- 合并所有其他值 2-by2 使用
zip
. This discussion 提供更多详细信息。
[float("{}{}".format(a, b)) for a, b in zip(x[2::2], x[3::2])]
将此列表转换为 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
我正在寻求拆分数据方面的帮助。我的数据有千位分隔符的空格,但我的时间戳之间也有空格。
这是数据的示例(当前为 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
我认为我正在尝试以一种奇怪且过于复杂的方式解决这个问题。在一个例子中,我删除了所有空格,然后拆分我所做的日期:
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
肯定有更快捷的方法来解决这个问题。谁能帮帮我?
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)
假设 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)
第一行将数据框转换为列表列表,根据需要拆分字符串。使用了一个特定的技巧:点或冒号后跟数字是属于一列的最后一个 space 分隔项(冒号表示时间戳,点表示浮点数)。
第二个从除第一个(时间戳)之外的所有列中删除所有 spaces,它只删除尾随的 spaces。
下一篇根据您的意愿创建列名。
最后一个从列表中重建数据帧。
你可以试试:
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)})
解释:
- 使用
df[df.columns[0]]
选择唯一的列后,使用pandas.Series.str.split
根据所有 space 拆分此列。正则表达式很简单\s+
:df[df.columns[0]].str.split(r"\s+")
- 使用
apply
在每行上应用自定义函数。- 首先通过将前 2 个元素与 space 合并来重新创建日期,转换为日期并将其包装在列表中:
[pd.Timestamp(" ".join(x[:2]))]
- 合并所有其他值 2-by2 使用
zip
. This discussion 提供更多详细信息。
- 首先通过将前 2 个元素与 space 合并来重新创建日期,转换为日期并将其包装在列表中:
[float("{}{}".format(a, b)) for a, b in zip(x[2::2], x[3::2])]
将此列表转换为
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