program tip

Pandas는 데이터 프레임을 튜플 배열로 변환합니다.

radiobox 2020. 8. 14. 07:36
반응형

Pandas는 데이터 프레임을 튜플 배열로 변환합니다.


pandas를 사용하여 일부 데이터를 조작했으며 이제 데이터베이스에 일괄 저장을 수행하고 싶습니다. 이를 위해서는 데이터 프레임을 튜플 배열로 변환해야합니다. 각 튜플은 데이터 프레임의 "행"에 해당합니다.

내 DataFrame은 다음과 같습니다.

In [182]: data_set
Out[182]: 
  index data_date   data_1  data_2
0  14303 2012-02-17  24.75   25.03 
1  12009 2012-02-16  25.00   25.07 
2  11830 2012-02-15  24.99   25.15 
3  6274  2012-02-14  24.68   25.05 
4  2302  2012-02-13  24.62   24.77 
5  14085 2012-02-10  24.38   24.61 

다음과 같은 튜플 배열로 변환하고 싶습니다.

[(datetime.date(2012,2,17),24.75,25.03),
(datetime.date(2012,2,16),25.00,25.07),
...etc. ]

이를 효율적으로 수행 할 수있는 방법에 대한 제안이 있습니까?


어때 :

subset = data_set[['data_date', 'data_1', 'data_2']]
tuples = [tuple(x) for x in subset.values]

list(data_set.itertuples(index=False))

17.1부터 위는 namedtuples 목록을 반환합니다 .

일반 튜플 목록을 원하면 name=None인수로 전달하십시오.

list(data_set.itertuples(index=False, name=None))

일반적인 방법 :

[tuple(x) for x in data_set.to_records(index=False)]

동기 부여
많은 데이터 세트는 속도 / 효율성에 관심을 가질만큼 충분히 큽니다. 그래서 저는 그 정신으로이 솔루션을 제공합니다. 그것은 또한 간결합니다.

비교를 위해 index열을 삭제하겠습니다.

df = data_set.drop('index', 1)

솔루션
사용 zip및 이해를 제안합니다

list(zip(*[df[c].values.tolist() for c in df]))

[('2012-02-17', 24.75, 25.03),
 ('2012-02-16', 25.0, 25.07),
 ('2012-02-15', 24.99, 25.15),
 ('2012-02-14', 24.68, 25.05),
 ('2012-02-13', 24.62, 24.77),
 ('2012-02-10', 24.38, 24.61)]

특정 열 하위 집합을 처리하려는 경우에도 유연합니다. 이미 표시 한 열이 원하는 하위 집합이라고 가정합니다.

list(zip(*[df[c].values.tolist() for c in ['data_date', 'data_1', 'data_2']))

[('2012-02-17', 24.75, 25.03),
 ('2012-02-16', 25.0, 25.07),
 ('2012-02-15', 24.99, 25.15),
 ('2012-02-14', 24.68, 25.05),
 ('2012-02-13', 24.62, 24.77),
 ('2012-02-10', 24.38, 24.61)]

다음은 모두 동일한 결과를 생성합니다.

  • [tuple(x) for x in df.values]
  • df.to_records(index=False).tolist()
  • list(map(tuple,df.values))
  • list(map(tuple, df.itertuples(index=False)))

더 빠른 것은 무엇입니까?
zip이해력이 훨씬 빠릅니다.

%timeit [tuple(x) for x in df.values]
%timeit list(map(tuple, df.itertuples(index=False)))
%timeit df.to_records(index=False).tolist()
%timeit list(map(tuple,df.values))
%timeit list(zip(*[df[c].values.tolist() for c in df]))

작은 데이터

10000 loops, best of 3: 55.7 µs per loop
1000 loops, best of 3: 596 µs per loop
10000 loops, best of 3: 38.2 µs per loop
10000 loops, best of 3: 54.3 µs per loop
100000 loops, best of 3: 12.9 µs per loop

대용량 데이터

10 loops, best of 3: 58.8 ms per loop
10 loops, best of 3: 43.9 ms per loop
10 loops, best of 3: 29.3 ms per loop
10 loops, best of 3: 53.7 ms per loop
100 loops, best of 3: 6.09 ms per loop

다음 은 그림과 같이 of 를 반환 하는 벡터화 된 접근 방식 (데이터 프레임 data_setdf대신 정의해야 한다고 가정 )입니다 .listtuples

>>> df.set_index(['data_date'])[['data_1', 'data_2']].to_records().tolist()

생성 :

[(datetime.datetime(2012, 2, 17, 0, 0), 24.75, 25.03),
 (datetime.datetime(2012, 2, 16, 0, 0), 25.0, 25.07),
 (datetime.datetime(2012, 2, 15, 0, 0), 24.99, 25.15),
 (datetime.datetime(2012, 2, 14, 0, 0), 24.68, 25.05),
 (datetime.datetime(2012, 2, 13, 0, 0), 24.62, 24.77),
 (datetime.datetime(2012, 2, 10, 0, 0), 24.38, 24.61)]

The idea of setting datetime column as the index axis is to aid in the conversion of the Timestamp value to it's corresponding datetime.datetime format equivalent by making use of the convert_datetime64 argument in DF.to_records which does so for a DateTimeIndex dataframe.

This returns a recarray which could be then made to return a list using .tolist


More generalized solution depending on the use case would be:

df.to_records().tolist()                              # Supply index=False to exclude index

This answer doesn't add any answers that aren't already discussed, but here are some speed results. I think this should resolve questions that came up in the comments. All of these look like they are O(n), based on these three values.

TL;DR: tuples = list(df.itertuples(index=False, name=None)) and tuples = list(zip(*[df[c].values.tolist() for c in df])) are tied for the fastest.

I did a quick speed test on results for three suggestions here:

  1. The zip answer from @pirsquared: tuples = list(zip(*[df[c].values.tolist() for c in df]))
  2. The accepted answer from @wes-mckinney: tuples = [tuple(x) for x in df.values]
  3. The itertuples answer from @ksindi with the name=None suggestion from @Axel: tuples = list(df.itertuples(index=False, name=None))
from numpy import random
import pandas as pd


def create_random_df(n):
    return pd.DataFrame({"A": random.randint(n, size=n), "B": random.randint(n, size=n)})

Small size:

df = create_random_df(10000)
%timeit tuples = list(zip(*[df[c].values.tolist() for c in df]))
%timeit tuples = [tuple(x) for x in df.values]
%timeit tuples = list(df.itertuples(index=False, name=None))

Gives:

1.66 ms ± 200 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
15.5 ms ± 1.52 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.74 ms ± 75.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Larger:

df = create_random_df(1000000)
%timeit tuples = list(zip(*[df[c].values.tolist() for c in df]))
%timeit tuples = [tuple(x) for x in df.values]
%timeit tuples = list(df.itertuples(index=False, name=None))

Gives:

202 ms ± 5.91 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
1.52 s ± 98.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
209 ms ± 11.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

As much patience as I have:

df = create_random_df(10000000)
%timeit tuples = list(zip(*[df[c].values.tolist() for c in df]))
%timeit tuples = [tuple(x) for x in df.values]
%timeit tuples = list(df.itertuples(index=False, name=None))

Gives:

1.78 s ± 118 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
15.4 s ± 222 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
1.68 s ± 96.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

The zip version and the itertuples version are within the confidence intervals each other. I suspect that they are doing the same thing under the hood.

These speed tests are probably irrelevant though. Pushing the limits of my computer's memory doesn't take a huge amount of time, and you really shouldn't be doing this on a large data set. Working with those tuples after doing this will end up being really inefficient. It's unlikely to be a major bottleneck in your code, so just stick with the version you think is most readable.


The most efficient and easy way:

list(data_set.to_records())

You can filter the columns you need before this call.


More pythonic way:

df = data_set[['data_date', 'data_1', 'data_2']]
map(tuple,df.values)

#try this one:

tuples = list(zip(data_set["data_date"], data_set["data_1"],data_set["data_2"]))
print (tuples)

참고URL : https://stackoverflow.com/questions/9758450/pandas-convert-dataframe-to-array-of-tuples

반응형