【问题标题】:Pandas: select rows based on a condition applied to stringPandas:根据应用于字符串的条件选择行
【发布时间】:2017-04-05 02:27:05
【问题描述】:

使用数据帧字典,每个键都是整数0, ..., 999,每个值都是这样的数据帧:

     A         B
1    10010001  17
2    10020001  5
3    10020002  11
4    10020003  2
5    10030001  86
...

我需要遍历整个字典,并将 A 列中第 3 位和第 4 位等于02 的所有行放在一个新的数据框中。在我的示例中,只有第 2、3 和 4 行会形成新的数据框。 A 列的所有值都是字符串。

pandas 中执行此操作的最有效方法是什么?

【问题讨论】:

  • 字典键在这方面有什么作用吗?
  • 不,他们没有。目前它们代表n 不同的数据帧,但在此任务结束时将只有一个“选定”数据帧。

标签: python string pandas dictionary


【解决方案1】:

下面的内容怎么样,d是你的字典:

pd.concat((v[v.A.str[2:4] == '02'] for v in d.itervalues()))

您的 dict 包含重复 3 次的示例数据框和键 0-2

d = dict(zip(range(3), [df]*3))

这会产生:

          A   B
2  10020001   5
3  10020002  11
4  10020003   2
2  10020001   5
3  10020002  11
4  10020003   2
2  10020001   5
3  10020002  11
4  10020003   2

这应该比创建行列表或使用列表推导更节省内存,因为它使用生成器表达式。由于直接索引,它也应该比使用正则表达式更快(假设您的数据值是标准化的)。


如果你不喜欢组合数组的索引,你总是可以reset_index()。例如:

y = pd.concat((v[v.A.str[2:4] == '02'] for v in d.itervalues()))
y.reset_index.drop('index', axis=1)

          A   B
0  10020001   5
1  10020002  11
2  10020003   2
3  10020001   5
4  10020002  11
5  10020003   2
6  10020001   5
7  10020002  11
8  10020003   2

【讨论】:

  • 嗯...不错的 sn-p,但这会重复行 - 我不需要。
  • “重复行”是指重复索引值还是重复数据帧的实际行?对于前者,请使用reset_index()。对于后者,行重复,因为我刚刚复制了您的示例数据框 3 次,所以应该重复。
  • 哦,是的,对不起,我只是指reset_index()
【解决方案2】:

第一行创建了一个索引器,它检查 A 列的第 3 和第 4 个字符,并为任何带有“02”的内容返回 True/False 布尔索引器。

应用该索引器后,第二行从原始数据框创建一个新数据框。

indexer = df['A'].apply(lambda x: x[2:4] == '02')
results = df.loc[indexer]

编辑:这是适用于数据框字典的上述解决方案。

frames = list()
for k in dictionary.keys():
    df = dictionary[k]
    indexer = df['A'].apply(lambda x: x[2:4] == '02')
    results = df.loc[results]
    frames.append(results)
output = pd.concat(frames)

【讨论】:

  • 我认为您应该扩展您的代码以遍历字典中的所有数据帧。否则,此代码仅存储迭代时在字典中探索的最后一个数据帧的结果。
  • 好的,谢谢。直到我发帖后才忘记这件事。请参阅上面针对规范的该部分进行的编辑。
  • 没问题!现在看起来很完美。干杯!
【解决方案3】:

试试这个:

keep = [] #hold all the rows you want to keep
for key in frame_dict.keys():
    frame = frame_dict[key]
    keep.append(
        frame[frame['A'].astype(str).str.contains('^\d\d02', regex=True)].copy()
    ) #append the rows matching regex for start of word (^), digit (\d), digit (\d), 02 
final = pd.concat(keep) #concatenate the matching rows

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-02
    • 2021-11-17
    • 2017-09-23
    • 1970-01-01
    • 2023-03-14
    • 2022-08-03
    • 2018-06-10
    相关资源
    最近更新 更多