【问题标题】:How to filter two Series of a Dataframe where the value of a list element is true in one of the series如何过滤数据框的两个系列,其中列表元素的值在其中一个系列中为真
【发布时间】:2020-01-22 04:05:52
【问题描述】:

我有一个数据框,其中两列的列表元素具有一对一的关系。 PhoneNumberPhonePrimary?.

PhoneNumber    PhonePrimary    City       Zip
__________________________________________________
[2107788451,   [True,
2107788451,     True,         San Antonio      71541
2107788451]     False]
-----------------------------------------------------
[5126508976,   [True,           
5124430261]     False]        Austin           78750

其他列只是奇异值元素,独立于这些列。我想将这些系列元素过滤到PhoneNumber 中的列表元素仅与PhonePrimary 的真实值匹配的元素。订单一致。有没有办法在不为结果创建新列的情况下做到这一点,比如使用过滤器?

结果如下:

PhoneNumber    PhonePrimary     City         Zip
__________________________________________________
[2107788451,    [True,
2107788451]     True]          San Antonio    71541
----------------------------------------------------
[5126508976]    [True]         Austin         78750

【问题讨论】:

  • 在您给定的示例中,值是作为数组/列表存储在一行中,还是在您的DataFrame 中存储为 3 行?
  • 过滤掉是什么意思?您能否举一个原始数据帧的虚拟示例,以及预期的结果是什么?
  • @r.ook 这两列的每一行都是一个不同大小的数组。有时数组只是像 [6502352235] 这样的一个元素,但它们始终是数组。
  • @JasonChia 我已经在我的问题中编辑了示例。就结果而言,每一行的值应该只是“PhonePrimary”的“True”和“PhoneNumber”的匹配电话号码。所以数组长度会减少,但仍然是数组。所以这些数组元素被过滤了。但其他列不受影响,“City”和“Zip”

标签: python pandas dataframe filtering


【解决方案1】:

这个想法是使用zip 遍历列表并保留True 值。 您可以这样做:

def func(f):
    r = [ [x, y] for x,y in zip(f['PhoneNumber'] ,f['PhonePrimary']) if y]

    # separate the values (PhoneNumber & PhonePrimary values)
    col1, fl = [x[0] for x in r], [x[1] for x in r] 

    return pd.Series([col1, fl], index=['PhoneNumber','PhonePrimary'])

df1 = df.apply(func, 1)
print(df1)

                      col1          flag 
0  [2107788451, 2107788452]  [True, True]

# Finally replace the columns from existing df
df[['PhoneNumber', 'PhonePrimary']] = df1[['PhoneNumber', 'PhonePrimary']]

样本数据

df = pd.DataFrame({'PhoneNumber': [[2107788451, 2107788452, 2107788453]], 
                   'PhonePrimary': [[True, True, False]],
                    'adr': ['San Antonio'],
                    'zip': 12345})

【讨论】:

  • 谢谢,但我无法获得这样的结果并理解这种方法。你为什么要创建一个包含所有这些的系列?实际上,我还有更多列,包括一个名为“_id”的索引,它是一个客户 ID。所以我需要为每一列做这个'+ [f[']]'?为什么索引是每一列。 id 应该只是 "_id" 吗?
【解决方案2】:

我不确定你是否还想要手术后的列表。

df = pd.DataFrame({'pn': [[2107788451,2107788451,2107788451], [5126508976,5124430261]], 'pp': [[True,True,False], [True,False]], 'city': ['sa', 'a'], 'zip': [71, 78]})

df = pd.concat([df['pn'].explode(), df['pp'].explode()], axis=1).query('pp == True').merge(df[['city', 'zip']], left_index=True, right_index=True)

如果$ 给您一个错误,请分两行完成

ndf = pd.concat([df['pn'].explode(), df['pp'].explode()], axis=1)
df = ndf[ndf['pp'].eq(True)].merge(df[['city', 'zip']], left_index=True, right_index=True)`
           pn    pp city  zip
0  2107788451  True   sa   71
0  2107788451  True   sa   71
1  5126508976  True    a   78
df = df.drop_duplicates(['pn'])

           pn    pp city  zip
0  2107788451  True   sa   71
1  5126508976  True    a   78

【讨论】:

  • 最好的解决方案是让单值数组不是数组,但是如果有多个真正的 Primary 只选择数组的第一个元素。所以每一行应该只有一个值,并且没有重复。所以索引实际上是一个person_member_id,。每人只限一排
  • AttributeError: 'Series' 对象没有属性 'explode'
  • 确保你有 pandas 0.25 版可以使用explode
  • SyntaxError: 无效语法 'PhonePrimary ?==True'
  • 哦,那个问号弄乱了查询,如果不能删除,你必须用 2 行来完成
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-27
相关资源
最近更新 更多