pandas:处理其值为列表的列
Posted
技术标签:
【中文标题】pandas:处理其值为列表的列【英文标题】:pandas: process a column whose value is a list 【发布时间】:2018-09-13 13:10:54 【问题描述】: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")]
密钥错误:-1
处理值为列表的 pandas 列的正确方法应该是什么?
【问题讨论】:
为了清楚起见,您能否解开这个嵌套表达式并指出哪个子表达式引发了异常?另外,请准备一个minimal reproducible example,您的问题必须与主题相关。 【参考方案1】:如果你想在没有新列的情况下在一行中完成,可以执行以下操作:
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】:使用.str[]
选择第一个元组,然后选择元组中的值,因为list
和tuple
是像string
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
s 和 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: 列表索引超出范围
【讨论】:
str[]
方法似乎是黑魔法。你是怎么发现的?
@CiprianTomoiagă - 来自 docs - 选择所有可迭代对象的更通用解决方案,而不仅仅是 string
s。 :)【参考方案3】:
你需要这样的东西:
创建一个仅包含阶段的新列:
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'))]
【讨论】:
以上是关于pandas:处理其值为列表的列的主要内容,如果未能解决你的问题,请参考以下文章
pandas 处理缺失值[dropna、drop、fillna]