【问题标题】:Python pandas dataframe : In an array column, if first item contains specific string then remove that item from arrayPython pandas dataframe:在数组列中,如果第一项包含特定字符串,则从数组中删除该项目
【发布时间】:2018-04-20 17:56:39
【问题描述】:

我有一个数据框,它有一些如下所示的列,其中包含不同大小的数组:

column
["a_id","b","c","d"]
["d_ID","e","f"]
["h","i","j","k","l"]
["id_m","n","o","p"]
["ID_q","r","s"]

如果第一项包含“ID”或“id”,我想从每行的数组中删除第一项。因此,预期的输出将如下所示:

column
["b","c","d"]
["e","f"]
["h","i","j","k","l"]
["n","o","p"]
["r","s"]

我们如何在数据框中包含数组元素的列中检查这一点?

【问题讨论】:

  • Nikita 如果您需要更快的帮助,您应该始终以正确的方式与我们分享您的数据。尝试使用 print(df.to_dict()) 在此处共享或限制为 5 行。 df.head().to_dict().

标签: python arrays python-3.x pandas dataframe


【解决方案1】:

使用str[0] 选择列表中的第一个值,然后通过contains 检查ID

m = df['column'].str[0].str.contains('ID', case=False)
print (m)
0     True
1     True
2    False
3     True
4     True
Name: column, dtype: bool

然后通过maskstr[1:] 将其删除:

df['column'] = df['column'].mask(m, df['column'].str[1:])
print (df)
            column
0        [b, c, d]
1           [e, f]
2  [h, i, j, k, l]
3        [n, o, p]
4           [r, s]

【讨论】:

  • 我在回答中添加了计时...请看一下!
  • @jezrael ,执行此操作后有可能“m = df['column'].str[0].str.contains('ID', case=False)”,它可能会返回几行的 NaN,所以这样做 "df['column'] = df['column'].mask(m, df['column'].str[1:])" 它会给出一些错误。有什么方法可以处理 NaN 的?
  • 是的,只使用.str.contains('ID', case=False, na=False)
  • OP 出于任何原因接受了这个答案,尽管我的回答更快......猜猜所有 OP 都不关心时间;)
【解决方案2】:

编辑:看来我误读了您的问题。此解决方案旨在删除包含'id'任何 元素,而不仅仅是第一个。

选项 1
我相信最直接的解决方案是使用apply:

df

               col
0  [a_id, b, c, d]
1     [d_ID, e, f]
2  [h, i, j, k, l]
3  [id_m, n, o, p]
4     [ID_q, r, s]


df.col = df.col.apply(lambda y: (y[1:] if 'id' in y[0].lower() else y))

df
               col
0        [b, c, d]
1           [e, f]
2  [h, i, j, k, l]
3        [n, o, p]
4           [r, s]

选项 2
或者,使用 列表推导

df.col = [(y[1:] if 'id' in y[0].lower() else y)  for y in df.col]  

df

               col
0        [b, c, d]
1           [e, f]
2  [h, i, j, k, l]
3        [n, o, p]
4           [r, s]

时间

df = pd.concat([df] * 100000)
%%timeit
m = df['col'].str[0].str.contains('ID', case=False)
df['col'].mask(m, df['col'].str[1:])

1 loop, best of 3: 917 ms per loop
%timeit [(y[1:] if 'id' in y[0].lower() else y)  for y in df.col]  
1 loop, best of 3: 272 ms per loop
%timeit df.col.apply(lambda y: (y[1:] if 'id' in y[0].lower() else y))
1 loop, best of 3: 309 ms per loop

【讨论】:

  • @coldspeed,我只想在数组的第一个元素中检查“id”或“ID”
  • @NikitaGupta 我在答案中添加了时间。看来list comp挺快的。
  • 使用列表理解方法,我收到错误:TypeError: 'method' object is not iterable
  • @NikitaGupta 不要做df.col,做df['col'],我认为这是你的问题。您的列名与绑定的数据框方法相同,并且存在名称冲突。如果您想要最明智的性能,还请记住时间安排。
猜你喜欢
  • 2012-04-17
  • 2020-02-14
  • 2013-10-04
  • 1970-01-01
  • 2018-07-05
  • 2016-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多