pandas:处理其值为列表的列

时间:2018-04-04 04:58:39

标签: python-2.7 list pandas filter tuples

id   stage_seq
1    [(A,1), (B,3), (C,5)]
2    [(B,2), (C,2), (E,6)]
3    [(B,2), (C,1), (D,2), (E,3)]

我想删除最后一个阶段是E的记录,而第二阶段到最后一个阶段的记录是D(即在上面的数据框中删除记录id = 3)。这是我的代码:

df = df[(df.stage_seq[-1][0] != "E") | (df.stage_seq[-2][0] != "D")]

但我收到以下错误:

  

df = df [(df.stage_seq [-1] [0]!=" E")| (df.stage_seq [-2] [0]!=" D")]

     

KeyError:-1

处理值为列表的pandas列的正确方法是什么?

3 个答案:

答案 0 :(得分:3)

使用.str[]选择第一个元组,然后使用元组中的值,因为listtuplestring s之类的迭代:

df = df[(df.stage_seq.str[-1].str[0] != "E") | (df.stage_seq.str[-2].str[0] != "D")]
print (df)
   id                 stage_seq
0   1  [(A, 1), (B, 3), (C, 5)]
1   2  [(B, 2), (C, 2), (E, 6)]

<强>详情:

print(df.stage_seq.str[-1])
0    (C, 5)
1    (E, 6)
2    (E, 3)
Name: stage_seq, dtype: object

print(df.stage_seq.str[-1].str[0])
0    C
1    E
2    E
Name: stage_seq, dtype: object

替代解决方案,如果NaN没有list comprehension且位置中存在值:

df = df[[x[-1][0] != 'E' or x[-2][0] != 'D' for x in df.stage_seq]]
print (df)
   id                 stage_seq
0   1  [(A, 1), (B, 3), (C, 5)]
1   2  [(B, 2), (C, 2), (E, 6)]

第一个解决方案也工作,如果想选择不存在的元组:

print(df.stage_seq.str[3])
0       NaN
1       NaN
2    (E, 3)
Name: stage_seq, dtype: object

print(df.stage_seq.str[3].str[0])
0    NaN
1    NaN
2      E
Name: stage_seq, dtype: object

print(df.stage_seq.str[3].str[0] == 'E')
0    False
1    False
2     True
Name: stage_seq, dtype: bool
print ([x[3][0] != 'E' != 'D' for x in df.stage_seq])
  

IndexError:列表索引超出范围

答案 1 :(得分:2)

如果您想在没有新列的情况下在一行中执行此操作,则可以执行以下操作:

df = df[df.stage_seq.apply(lambda x: x[-1][0] != 'E') | \
    df.stage_seq.apply(lambda x: x[-2][0] != 'D')]

结果是:

   id                 stage_seq
0   1  [(A, 1), (B, 3), (C, 5)]
1   2  [(B, 2), (C, 2), (E, 6)]

您的问题是您尝试访问df.stage_seq中的列表,但df.column[x][y]语法不会这样做。相反,您可以使用lambda函数访问df.stage_seq的每个单元格的内容,然后然后选择所需的列表元素。请注意,这假设实际数据帧中的所有单元格实际上都具有这些位置的值。

答案 2 :(得分:0)

你需要这样的东西:

创建一个仅包含阶段的新列:

df['stage']  = df['stage_seq'].apply(lambda x: "".join(w for w,x in x))

为最后一个和第二个最后一个阶段创建两个单独的列

df['last_stage'] = df['stage'].apply(lambda x: x[-1])
df['2ndlast_stage'] = df['stage'].apply(lambda x: x[-2])

过滤数据框

df1=df[~((df['last_stage'] == 'E') & (df['2ndlast_stage'] == 'D'))]