我的df看起来像这样:
name surname device
anna smith Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E304
petr lebowski Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:48.0) Gecko/20100101 Firefox/48.0
eveline jones Mozilla/5.0 (Linux; Android 6.0.1; SAMSUNG SM-G903F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/5.4 Chrome/51.0.2704.106 Mobile Safari/537.36
我的目标是将这些行拆分为多个列,并选择某些值来创建新列,以便新数据框如下所示:
name surname device column1 column2 column3
anna smith as in df iPhone CPU iPhone OS 10_3_1 Mac OS X
petr lebowski as in df Macintosh Intel Mac OS X 10.6 rv:48.0
eveline jones as in df Linux Android 6.0.1 SAMSUNG SM-G903F Build/MMB29K
所以基本上我只想从这些行中选择某些值:只是用括号分隔的那些值;'。'。
我知道如何用符号分割符号:
def split_it(string):
return re.findall(r"[\w']+|[.,!?;]", string)
以及如何使用拆分行创建新列:
df['device'].str[1:-1].str.split(',', expand=True)
但是如何只选择某些值并用它们创建列不明白......
答案 0 :(得分:1)
你需要一个更好的正则表达式:
pattern = re.compile(r"\((.+?); (.+?)(?: like|;) (.+?)\)")
new_columns = df.device.str.extract(pattern, expand=False)
你甚至可以预先命名:
new_columns = df.Device.str.extract(r"\((?P<column1>.+?); (?P<column2>.+?)(?: like|;) (?P<column3>.+?)\)", expand=False)
然后,您只需要将join
与其余数据一起返回:
df = df.join(new_columns)
答案 1 :(得分:1)
您可以利用较新的regex
module和一些编程逻辑:
import pandas as pd, regex as re
# your df here
rx = re.compile(r'(?:\G(?!\A)|^[^()]*\()([^();]+);?')
def getter(col):
# default empty dict
empty = {'column1': '', 'column2': '', 'column3': ''}
# generate results with a comprehension
matches = {'column{}'.format(idx): val
for idx, val in enumerate(rx.findall(col), 1)}
return pd.Series(dict(empty, **matches))
df[["column1", "column2", "column3"]] = df["device"].apply(getter)
print(df[["column1", "column2", "column3"]])
这样可以为你的例子
column1 column2 \
0 iPhone CPU iPhone OS 10_3_1 like Mac OS X
1 Macintosh Intel Mac OS X 10.6
2 Linux Android 6.0.1
column3
0
1 rv:48.0
2 SAMSUNG SM-G903F Build/MMB29K
<小时/>
虽然肯定不完美,但我们的想法是匹配;
和(
内的)
。在这里,需要\G
匹配最后一个匹配停止的地方:
(?: # non-capturing group
\G(?!\A) # match where the last match stopped, not the beginning
| # or
^[^()]*\( # find the first (
)
( # capture group 1
[^();]+ # anything not (, ) or ; at least once
)
;? # semicolon optionally
之后,函数getter
会返回一个新的pd.Series()
,该df
将保存在getter()
中。 ln -s /source_folder /home/user/public_html/target_folder
内的逻辑覆盖空字典。