3

我对 python 比较陌生,但过去几周一直在虔诚地使用 Wes Kinney 的“用于数据分析的 Python”。我花了几个小时试图找出解决当前问题的方法,但我需要一些帮助。但是,我有一个数据集,其中包含本日历年发送的货物的详细信息;当我每个月都会获得新数据时,一些细节可能已经改变。我已经弄清楚如何识别发生变化的货物,以及如何识别这些变化可能是什么。

所以,假设我已经确定这些货物(在数据框中,原始)已经改变:

ID      Code    Mode    Amount    From     To     Weight    Cube    Service_Date
MNO123  BBB     Air     50        M1234    M9876  60        6       1-1-2013
GHI123  AAA     Air     50        M1234    M9876  80        8       1-1-2013
JKL123  AAA     Ship    50        M1234    M9876  70        7       1-1-2013

我已经确定了潜在的变化(在数据框中,变化):

ID      Code    Mode    Amount    From     To     Weight    Cube    Service_Date
MNO123  BBB     Air     50        M1234    M9876  60        6       2-2-2013
MNO123  BBB     Air     60        M1234    M9876  60        6       2-2-2013
MNO123  BBB     Air     70        M1234    M1111  60        6       2-2-2013
GHI123  AAA     Air     65        M1234    M9876  80        8       1-1-2013
JKL123  AAA     Ship    65        M1234    M9876  70        7       1-1-2013
JKL123  AAA     Ship    65        M1234    M9876  70        8       1-1-2013

我要做的就是向更改数据框中添加一个计数列,该列总计与原始数据框中的相应值匹配的值的数量。因此,因为 code、mode、amount、from、to、weight 和 cube 匹配,所以 count 列将在第一次观察时获得 7 的值。类似地,但少了一个匹配值,第二个观察值的计数值为 6,第三个观察值的计数值为 5。

我正在寻找的结果如下:

ID      Code    Mode    Amount    From     To     Weight    Cube    Service_Date  Count
MNO123  BBB     Air     50        M1234    M9876  60        6       2-2-2013      7
MNO123  BBB     Air     60        M1234    M9876  60        6       2-2-2013      6
MNO123  BBB     Air     70        M1234    M1111  60        6       2-2-2013      5
GHI123  AAA     Air     65        M1234    M9876  80        8       1-1-2013      7
JKL123  AAA     Ship    65        M1234    M9876  70        7       1-1-2013      7
JKL123  AAA     Ship    65        M1234    M9876  70        8       1-1-2013      6

浏览了 Wes 的书和该站点上的许多类似的帖子后,我相信我需要使用df.iterrows(),但我在迭代两个数据帧同时检查和计算匹配值的过程中遇到了困难。

这是我最近的尝试:

for i in changes.iterrows():
  for i in original.iterrows():
    changes['count'] = 0
    if changes(i) == original(i):
      changes['count'] +=1

提前感谢您的时间和努力!

4

2 回答 2

1

这是一种方法:

确保将原始数据帧和更改数据帧的索引都设置为 ID:

In [11]: orignal.set_index('ID', inplace=True)

In [12]: original
Out[12]: 
       Code  Mode  Amount   From     To  Weight  Cube Service_Date
ID                                                                
MNO123  BBB   Air      50  M1234  M9876      60     6     1-1-2013
GHI123  AAA   Air      50  M1234  M9876      80     8     1-1-2013
JKL123  AAA  Ship      50  M1234  M9876      70     7     1-1-2013

您还必须在这里做一些小技巧,以允许我们使用 eq DataFrame 方法,不幸的是,这会进行排序(或者您可以跟踪原始唯一索引)。

In [13]: changes = changes.set_index('ID').sort_index()

选择您感兴趣的列(或者您可以删除 Service_Date 列):

In [14]: count_columns = ['Code', 'Mode', 'Amount', 'From', 'To', 'Weight', 'Cube']

然后可以使用 eq DataFrame 方法:

In [15]: changes.eq(original)[count_columns]
Out[15]: 
        Code  Mode Amount  From     To Weight   Cube
ID                                                  
GHI123  True  True  False  True   True   True   True
JKL123  True  True  False  True   True   True   True
JKL123  True  True  False  True   True   True  False
MNO123  True  True   True  True   True   True   True
MNO123  True  True  False  True   True   True   True
MNO123  True  True  False  True  False   True   True

并对每一行求和:

In [16]: changes.eq(original)[count_columns].sum(1)
Out[16]: 
ID
GHI123    6
JKL123    6
JKL123    5
MNO123    7
MNO123    6
MNO123    5
dtype: int64

In [17]: changes['match'] = changes.eq(original)[count_columns].sum(1).values

In [18]: changes
Out[18]: 
       Code  Mode  Amount   From     To  Weight  Cube Service_Date  match
ID                                                                       
GHI123  AAA   Air      65  M1234  M9876      80     8     1-1-2013      6
JKL123  AAA  Ship      65  M1234  M9876      70     7     1-1-2013      6
JKL123  AAA  Ship      65  M1234  M9876      70     8     1-1-2013      5
MNO123  BBB   Air      50  M1234  M9876      60     6     2-2-2013      7
MNO123  BBB   Air      60  M1234  M9876      60     6     2-2-2013      6
MNO123  BBB   Air      70  M1234  M1111      60     6     2-2-2013      5

注意:计数似乎与您的略有不同...

于 2013-09-09T19:11:45.237 回答
0

您不需要迭代行:

def count_equal(row, original, ID):
    """Counts the number of equal elements between row and original.ix[ID]"""
    equal_values = (row == original[original.ID == ID]).values
    return equal_values.sum() - 1  # substract 1 because ID doesn't count

changes['count'] = changes.apply(count_equal, args=(original, 'MNO123'), axis=1)
于 2013-09-09T03:24:33.087 回答